1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-03-20 14:25:18 +01:00

remove leaked box in REQUEST_POOL and RESPONSE_POOL (#1896)

This commit is contained in:
fakeshadow 2021-01-09 23:40:20 +08:00 committed by GitHub
parent 6575ee93f2
commit f6cc829758
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -34,7 +34,9 @@ bitflags! {
pub trait Head: Default + 'static { pub trait Head: Default + 'static {
fn clear(&mut self); fn clear(&mut self);
fn pool() -> &'static MessagePool<Self>; fn with_pool<F, R>(f: F) -> R
where
F: FnOnce(&MessagePool<Self>) -> R;
} }
#[derive(Debug)] #[derive(Debug)]
@ -69,8 +71,11 @@ impl Head for RequestHead {
self.extensions.get_mut().clear(); self.extensions.get_mut().clear();
} }
fn pool() -> &'static MessagePool<Self> { fn with_pool<F, R>(f: F) -> R
REQUEST_POOL.with(|p| *p) where
F: FnOnce(&MessagePool<Self>) -> R,
{
REQUEST_POOL.with(|p| f(p))
} }
} }
@ -344,7 +349,7 @@ pub struct Message<T: Head> {
impl<T: Head> Message<T> { impl<T: Head> Message<T> {
/// Get new message from the pool of objects /// Get new message from the pool of objects
pub fn new() -> Self { pub fn new() -> Self {
T::pool().get_message() T::with_pool(|p| p.get_message())
} }
} }
@ -373,7 +378,7 @@ impl<T: Head> std::ops::DerefMut for Message<T> {
impl<T: Head> Drop for Message<T> { impl<T: Head> Drop for Message<T> {
fn drop(&mut self) { fn drop(&mut self) {
if Rc::strong_count(&self.head) == 1 { if Rc::strong_count(&self.head) == 1 {
T::pool().release(self.head.clone()); T::with_pool(|p| p.release(self.head.clone()))
} }
} }
} }
@ -426,18 +431,17 @@ pub struct MessagePool<T: Head>(RefCell<Vec<Rc<T>>>);
/// Request's objects pool /// Request's objects pool
pub struct BoxedResponsePool(RefCell<Vec<Box<ResponseHead>>>); pub struct BoxedResponsePool(RefCell<Vec<Box<ResponseHead>>>);
thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create()); thread_local!(static REQUEST_POOL: MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: &'static BoxedResponsePool = BoxedResponsePool::create()); thread_local!(static RESPONSE_POOL: BoxedResponsePool = BoxedResponsePool::create());
impl<T: Head> MessagePool<T> { impl<T: Head> MessagePool<T> {
fn create() -> &'static MessagePool<T> { fn create() -> MessagePool<T> {
let pool = MessagePool(RefCell::new(Vec::with_capacity(128))); MessagePool(RefCell::new(Vec::with_capacity(128)))
Box::leak(Box::new(pool))
} }
/// Get message from the pool /// Get message from the pool
#[inline] #[inline]
fn get_message(&'static self) -> Message<T> { fn get_message(&self) -> Message<T> {
if let Some(mut msg) = self.0.borrow_mut().pop() { if let Some(mut msg) = self.0.borrow_mut().pop() {
// Message is put in pool only when it's the last copy. // Message is put in pool only when it's the last copy.
// which means it's guaranteed to be unique when popped out. // which means it's guaranteed to be unique when popped out.
@ -463,14 +467,13 @@ impl<T: Head> MessagePool<T> {
} }
impl BoxedResponsePool { impl BoxedResponsePool {
fn create() -> &'static BoxedResponsePool { fn create() -> BoxedResponsePool {
let pool = BoxedResponsePool(RefCell::new(Vec::with_capacity(128))); BoxedResponsePool(RefCell::new(Vec::with_capacity(128)))
Box::leak(Box::new(pool))
} }
/// Get message from the pool /// Get message from the pool
#[inline] #[inline]
fn get_message(&'static self, status: StatusCode) -> BoxedResponseHead { fn get_message(&self, status: StatusCode) -> BoxedResponseHead {
if let Some(mut head) = self.0.borrow_mut().pop() { if let Some(mut head) = self.0.borrow_mut().pop() {
head.reason = None; head.reason = None;
head.status = status; head.status = status;