@@ -86,6 +86,7 @@ use mea::semaphore::Semaphore;
8686use crate :: ManageObject ;
8787use crate :: ObjectStatus ;
8888use crate :: QueueStrategy ;
89+ use crate :: RecycleCancelledStrategy ;
8990use crate :: RetainResult ;
9091use crate :: mutex:: Mutex ;
9192use crate :: retain_spec;
@@ -101,6 +102,9 @@ pub struct PoolConfig {
101102 ///
102103 /// Determines the order of objects being queued and dequeued.
103104 pub queue_strategy : QueueStrategy ,
105+
106+ /// Strategy when recycling object has been cancelled.
107+ pub recycle_cancelled_strategy : RecycleCancelledStrategy ,
104108}
105109
106110impl PoolConfig {
@@ -109,6 +113,7 @@ impl PoolConfig {
109113 Self {
110114 max_size,
111115 queue_strategy : QueueStrategy :: default ( ) ,
116+ recycle_cancelled_strategy : RecycleCancelledStrategy :: default ( ) ,
112117 }
113118 }
114119
@@ -117,6 +122,15 @@ impl PoolConfig {
117122 self . queue_strategy = queue_strategy;
118123 self
119124 }
125+
126+ /// Returns a new [`PoolConfig`] with the specified recycle cancelled strategy.
127+ pub fn with_recycle_cancelled_strategy (
128+ mut self ,
129+ recycle_cancelled_strategy : RecycleCancelledStrategy ,
130+ ) -> Self {
131+ self . recycle_cancelled_strategy = recycle_cancelled_strategy;
132+ self
133+ }
120134}
121135
122136/// The current pool status.
@@ -310,6 +324,7 @@ impl<M: ManageObject> Pool<M> {
310324 let mut unready_object = UnreadyObject {
311325 state : Some ( object) ,
312326 pool : Arc :: downgrade ( self ) ,
327+ recycle_cancelled_strategy : self . config . recycle_cancelled_strategy ,
313328 } ;
314329
315330 let state = unready_object. state ( ) ;
@@ -323,6 +338,10 @@ impl<M: ManageObject> Pool<M> {
323338 state. status . recycle_count += 1 ;
324339 state. status . recycled = Some ( std:: time:: Instant :: now ( ) ) ;
325340 break unready_object. ready ( permit) ;
341+ } else {
342+ // We need to manually detach here as the drop implementation
343+ // depends on the recycle cancelled strategy.
344+ unready_object. detach ( ) ;
326345 }
327346 }
328347 } ;
@@ -396,6 +415,11 @@ impl<M: ManageObject> Pool<M> {
396415 }
397416
398417 fn push_back ( & self , o : ObjectState < M :: Object > ) {
418+ self . return_to_pool ( o) ;
419+ self . users . fetch_sub ( 1 , Ordering :: Relaxed ) ;
420+ }
421+
422+ fn return_to_pool ( & self , o : ObjectState < M :: Object > ) {
399423 let mut slots = self . slots . lock ( ) ;
400424
401425 assert ! (
@@ -406,9 +430,6 @@ impl<M: ManageObject> Pool<M> {
406430 ) ;
407431
408432 slots. deque . push_back ( o) ;
409- drop ( slots) ;
410-
411- self . users . fetch_sub ( 1 , Ordering :: Relaxed ) ;
412433 }
413434
414435 fn detach_object ( & self , o : & mut M :: Object , ready : bool ) {
@@ -517,17 +538,30 @@ impl<M: ManageObject> Object<M> {
517538 }
518539}
519540
520- /// A wrapper of ObjectStatus that detaches the object from the pool when dropped.
541+ /// A wrapper of ObjectState used during the `is_recyclable` check in `Pool::get`.
542+ ///
543+ /// If the check passes, the object is converted to a ready `Object` via `ready()`.
544+ /// If the check fails, `detach()` should be called to permanently remove the object
545+ /// from the pool. If dropped without calling either method (due to being cancelled),
546+ /// the behavior depends on the pool's [`RecycleCancelledStrategy`] configuration.
521547struct UnreadyObject < M : ManageObject > {
522548 state : Option < ObjectState < M :: Object > > ,
523549 pool : Weak < Pool < M > > ,
550+ recycle_cancelled_strategy : RecycleCancelledStrategy ,
524551}
525552
526553impl < M : ManageObject > Drop for UnreadyObject < M > {
527554 fn drop ( & mut self ) {
528555 if let Some ( mut state) = self . state . take ( ) {
529556 if let Some ( pool) = self . pool . upgrade ( ) {
530- pool. detach_object ( & mut state. o , false ) ;
557+ match self . recycle_cancelled_strategy {
558+ RecycleCancelledStrategy :: Detach => {
559+ pool. detach_object ( & mut state. o , false ) ;
560+ }
561+ RecycleCancelledStrategy :: ReturnToPool => {
562+ pool. return_to_pool ( state) ;
563+ }
564+ }
531565 }
532566 }
533567 }
@@ -545,6 +579,14 @@ impl<M: ManageObject> UnreadyObject<M> {
545579 }
546580 }
547581
582+ fn detach ( & mut self ) {
583+ if let Some ( mut state) = self . state . take ( ) {
584+ if let Some ( pool) = self . pool . upgrade ( ) {
585+ pool. detach_object ( & mut state. o , false ) ;
586+ }
587+ }
588+ }
589+
548590 fn state ( & mut self ) -> & mut ObjectState < M :: Object > {
549591 // SAFETY: `state` is always `Some` when `UnreadyObject` is owned.
550592 self . state . as_mut ( ) . unwrap ( )
0 commit comments