1- use std:: { cell:: RefCell , collections:: BTreeMap , rc:: Rc } ;
1+ use std:: {
2+ cell:: { OnceCell , RefCell } ,
3+ collections:: BTreeMap ,
4+ rc:: Rc ,
5+ sync:: atomic:: AtomicBool ,
6+ } ;
27
38// Vector pooling minimum capacity threshold
49// Recommended threshold: 64
@@ -71,6 +76,10 @@ impl<T: Poolable> ObjectPool<T> {
7176 let bucket = objects. entry ( cap) . or_default ( ) ;
7277 bucket. push ( object) ;
7378 }
79+
80+ pub fn clear ( & self ) {
81+ self . objects . borrow_mut ( ) . clear ( ) ;
82+ }
7483}
7584
7685/// A smart pointer that holds a pooled object and automatically returns it to the pool when dropped.
@@ -130,9 +139,11 @@ impl<T: Poolable> std::ops::DerefMut for Pooled<T> {
130139}
131140
132141thread_local ! {
133- pub static USIZE_VEC_POOL : RefCell < Option < ObjectPool <Vec <usize >>>> = RefCell :: default ( ) ;
142+ pub static USIZE_VEC_POOL : OnceCell < ObjectPool <Vec <usize >>> = OnceCell :: default ( ) ;
134143}
135144
145+ pub static IN_USING_OBJECT_POOL : AtomicBool = AtomicBool :: new ( false ) ;
146+
136147/// Executes a function with object pooling enabled for the current thread.
137148///
138149/// This function temporarily enables a thread-local object pool for `Vec<usize>` allocations,
@@ -141,21 +152,35 @@ pub fn using_object_pool<F, R>(f: F) -> R
141152where
142153 F : FnOnce ( ) -> R ,
143154{
155+ IN_USING_OBJECT_POOL . store ( true , std:: sync:: atomic:: Ordering :: Relaxed ) ;
144156 // Initialize the thread-local pool if needed
145- USIZE_VEC_POOL . with ( |pool| {
146- let mut pool_ref = pool. borrow_mut ( ) ;
147- if pool_ref. is_none ( ) {
148- * pool_ref = Some ( ObjectPool :: default ( ) ) ;
149- }
157+ USIZE_VEC_POOL . with ( |once_cell| {
158+ once_cell. get_or_init ( ObjectPool :: default) ;
150159 } ) ;
151160
152161 let result = f ( ) ;
153162
154- // Clean up the pool to prevent memory retention
155- // This ensures no memory is held between different pooling sessions
156- USIZE_VEC_POOL . with ( |pool| {
157- pool. borrow_mut ( ) . take ( ) ;
163+ IN_USING_OBJECT_POOL . store ( false , std:: sync:: atomic:: Ordering :: Relaxed ) ;
164+ USIZE_VEC_POOL . with ( |once_cell| {
165+ if let Some ( pool) = once_cell. get ( ) {
166+ pool. clear ( ) ;
167+ }
158168 } ) ;
159169
160170 result
161171}
172+
173+ /// Cleans up the object pool when not in pooling mode to prevent memory retention.
174+ ///
175+ /// This function is called automatically after map operations complete to ensure
176+ /// that memory is not retained unnecessarily outside of pooling contexts.
177+ pub fn cleanup_idle_object_pool ( ) {
178+ // Only clear if we're not in an explicit pooling context
179+ if !IN_USING_OBJECT_POOL . load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
180+ USIZE_VEC_POOL . with ( |once_cell| {
181+ if let Some ( pool) = once_cell. get ( ) {
182+ pool. clear ( ) ;
183+ }
184+ } ) ;
185+ }
186+ }
0 commit comments