1
1
///! Reference counter for channels.
2
+
2
3
use std:: isize;
3
4
use std:: ops;
4
5
use std:: process;
5
- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
6
+ use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
6
7
7
8
/// Reference counter internals.
8
9
struct Counter < C > {
@@ -12,6 +13,9 @@ struct Counter<C> {
12
13
/// The number of receivers associated with the channel.
13
14
receivers : AtomicUsize ,
14
15
16
+ /// Set to `true` if the last sender or the last receiver reference deallocates the channel.
17
+ destroy : AtomicBool ,
18
+
15
19
/// The internal channel.
16
20
chan : C ,
17
21
}
@@ -21,6 +25,7 @@ pub fn new<C>(chan: C) -> (Sender<C>, Receiver<C>) {
21
25
let counter = Box :: into_raw ( Box :: new ( Counter {
22
26
senders : AtomicUsize :: new ( 1 ) ,
23
27
receivers : AtomicUsize :: new ( 1 ) ,
28
+ destroy : AtomicBool :: new ( false ) ,
24
29
chan,
25
30
} ) ) ;
26
31
let s = Sender { counter } ;
@@ -60,7 +65,9 @@ impl<C> Sender<C> {
60
65
/// Function `disconnect` will be called if this is the last sender reference.
61
66
pub unsafe fn release < F : FnOnce ( & C ) -> bool > ( & self , disconnect : F ) {
62
67
if self . counter ( ) . senders . fetch_sub ( 1 , Ordering :: AcqRel ) == 1 {
63
- if !disconnect ( & self . counter ( ) . chan ) {
68
+ disconnect ( & self . counter ( ) . chan ) ;
69
+
70
+ if self . counter ( ) . destroy . swap ( true , Ordering :: AcqRel ) {
64
71
drop ( Box :: from_raw ( self . counter ) ) ;
65
72
}
66
73
}
@@ -113,7 +120,9 @@ impl<C> Receiver<C> {
113
120
/// Function `disconnect` will be called if this is the last receiver reference.
114
121
pub unsafe fn release < F : FnOnce ( & C ) -> bool > ( & self , disconnect : F ) {
115
122
if self . counter ( ) . receivers . fetch_sub ( 1 , Ordering :: AcqRel ) == 1 {
116
- if !disconnect ( & self . counter ( ) . chan ) {
123
+ disconnect ( & self . counter ( ) . chan ) ;
124
+
125
+ if self . counter ( ) . destroy . swap ( true , Ordering :: AcqRel ) {
117
126
drop ( Box :: from_raw ( self . counter ) ) ;
118
127
}
119
128
}
0 commit comments