11use std:: cmp:: min;
2+ use std:: sync:: Arc ;
23use std:: time:: Instant ;
34
45use futures_channel:: oneshot;
6+ use parking_lot:: Mutex ;
57
68use crate :: api:: { Builder , ManageConnection } ;
79use std:: collections:: VecDeque ;
810
11+ /// The guts of a `Pool`.
12+ #[ allow( missing_debug_implementations) ]
13+ pub ( crate ) struct SharedPool < M >
14+ where
15+ M : ManageConnection + Send ,
16+ {
17+ pub ( crate ) statics : Builder < M > ,
18+ pub ( crate ) manager : M ,
19+ pub ( crate ) internals : Mutex < PoolInternals < M > > ,
20+ }
21+
22+ impl < M > SharedPool < M >
23+ where
24+ M : ManageConnection + Send ,
25+ {
26+ pub ( crate ) fn new ( statics : Builder < M > , manager : M ) -> Self {
27+ Self {
28+ statics,
29+ manager,
30+ internals : Mutex :: new ( PoolInternals :: default ( ) ) ,
31+ }
32+ }
33+ }
34+
935/// The pool data that must be protected by a lock.
1036#[ allow( missing_debug_implementations) ]
1137pub ( crate ) struct PoolInternals < M >
1238where
1339 M : ManageConnection ,
1440{
15- waiters : VecDeque < oneshot:: Sender < Conn < M :: Connection > > > ,
41+ waiters : VecDeque < oneshot:: Sender < InternalsGuard < M > > > ,
1642 conns : VecDeque < IdleConn < M :: Connection > > ,
1743 num_conns : u32 ,
1844 pending_conns : u32 ,
@@ -31,27 +57,31 @@ where
3157 . map ( |idle| ( idle. conn , self . wanted ( config) ) )
3258 }
3359
34- pub ( crate ) fn put ( & mut self , conn : Conn < M :: Connection > , approval : Option < Approval > ) {
35- let mut conn = IdleConn :: from ( conn) ;
60+ pub ( crate ) fn put (
61+ & mut self ,
62+ conn : Conn < M :: Connection > ,
63+ approval : Option < Approval > ,
64+ pool : Arc < SharedPool < M > > ,
65+ ) {
3666 if approval. is_some ( ) {
3767 self . pending_conns -= 1 ;
3868 self . num_conns += 1 ;
3969 }
4070
41- loop {
42- if let Some ( waiter) = self . waiters . pop_front ( ) {
43- // This connection is no longer idle, send it back out.
44- match waiter. send ( conn . conn ) {
45- Ok ( _ ) => break ,
46- // Oops, that receiver was gone. Loop and try again.
47- Err ( c ) => conn . conn = c ,
71+ let mut guard = InternalsGuard :: new ( conn , pool ) ;
72+ while let Some ( waiter) = self . waiters . pop_front ( ) {
73+ // This connection is no longer idle, send it back out
74+ match waiter. send ( guard ) {
75+ Ok ( ( ) ) => return ,
76+ Err ( g ) => {
77+ guard = g ;
4878 }
49- } else {
50- // Queue it in the idle queue.
51- self . conns . push_back ( conn) ;
52- break ;
5379 }
5480 }
81+
82+ // Queue it in the idle queue
83+ self . conns
84+ . push_back ( IdleConn :: from ( guard. conn . take ( ) . unwrap ( ) ) ) ;
5585 }
5686
5787 pub ( crate ) fn connect_failed ( & mut self , _: Approval ) {
77107
78108 pub ( crate ) fn push_waiter (
79109 & mut self ,
80- waiter : oneshot:: Sender < Conn < M :: Connection > > ,
110+ waiter : oneshot:: Sender < InternalsGuard < M > > ,
81111 config : & Builder < M > ,
82112 ) -> ApprovalIter {
83113 self . waiters . push_back ( waiter) ;
@@ -137,6 +167,33 @@ where
137167 }
138168}
139169
170+ pub ( crate ) struct InternalsGuard < M : ManageConnection > {
171+ conn : Option < Conn < M :: Connection > > ,
172+ pool : Arc < SharedPool < M > > ,
173+ }
174+
175+ impl < M : ManageConnection > InternalsGuard < M > {
176+ fn new ( conn : Conn < M :: Connection > , pool : Arc < SharedPool < M > > ) -> Self {
177+ Self {
178+ conn : Some ( conn) ,
179+ pool,
180+ }
181+ }
182+
183+ pub ( crate ) fn extract ( & mut self ) -> Conn < M :: Connection > {
184+ self . conn . take ( ) . unwrap ( ) // safe: can only be `None` after `Drop`
185+ }
186+ }
187+
188+ impl < M : ManageConnection > Drop for InternalsGuard < M > {
189+ fn drop ( & mut self ) {
190+ if let Some ( conn) = self . conn . take ( ) {
191+ let mut locked = self . pool . internals . lock ( ) ;
192+ locked. put ( conn, None , self . pool . clone ( ) ) ;
193+ }
194+ }
195+ }
196+
140197#[ must_use]
141198pub ( crate ) struct ApprovalIter {
142199 num : usize ,
0 commit comments