1
+ use std:: cell:: Cell ;
2
+ use std:: future:: Future ;
1
3
use std:: marker:: PhantomData ;
4
+ use std:: pin:: Pin ;
5
+ use std:: ptr;
6
+ use std:: task:: { Context , Poll } ;
2
7
3
8
pub struct Sender < T > {
4
9
_p : PhantomData < T > ,
@@ -8,12 +13,74 @@ pub struct Receiver<T> {
8
13
_p : PhantomData < T > ,
9
14
}
10
15
16
+ pub ( crate ) struct Enter < ' a , T > {
17
+ _rx : & ' a mut Receiver < T > ,
18
+ }
19
+
11
20
pub fn pair < T > ( ) -> ( Sender < T > , Receiver < T > ) {
12
- unimplemented ! ( ) ;
21
+ let tx = Sender { _p : PhantomData } ;
22
+ let rx = Receiver { _p : PhantomData } ;
23
+ ( tx, rx)
24
+ }
25
+
26
+ // Tracks the pointer to `Option<T>`.
27
+ //
28
+ // TODO: Ensure wakers match?
29
+ thread_local ! ( static STORE : Cell <* mut ( ) > = Cell :: new( ptr:: null_mut( ) ) ) ;
30
+
31
+ // ===== impl Sender =====
32
+
33
+ impl < T : Unpin + ' static > Sender < T > {
34
+ pub fn send ( & mut self , value : T ) -> impl Future < Output = ( ) > {
35
+ Send { value : Some ( value) }
36
+ }
37
+ }
38
+
39
+ struct Send < T > {
40
+ value : Option < T > ,
13
41
}
14
42
15
- impl < T > Sender < T > {
16
- pub async fn send ( & mut self , value : T ) {
17
- unimplemented ! ( ) ;
43
+ impl < T : Unpin + ' static > Future for Send < T > {
44
+ type Output = ( ) ;
45
+
46
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < ( ) > {
47
+ if self . value . is_none ( ) {
48
+ return Poll :: Ready ( ( ) ) ;
49
+ }
50
+
51
+ STORE . with ( |cell| {
52
+ unsafe {
53
+ let ptr = cell. get ( ) as * mut Option < T > ;
54
+ let option_ref = ptr. as_mut ( ) . expect ( "invalid usage" ) ;
55
+
56
+ if option_ref. is_none ( ) {
57
+ * option_ref = self . value . take ( ) ;
58
+ }
59
+
60
+ Poll :: Pending
61
+ }
62
+ } )
63
+ }
64
+ }
65
+
66
+ // ===== impl Receiver =====
67
+
68
+ impl < T > Receiver < T > {
69
+ pub ( crate ) fn enter < ' a > ( & ' a mut self , dst : & ' a mut Option < T > ) -> Enter < ' a , T > {
70
+ STORE . with ( |cell| {
71
+ assert ! ( cell. get( ) . is_null( ) ) ;
72
+
73
+ cell. set ( dst as * mut _ as * mut ( ) ) ;
74
+ } ) ;
75
+
76
+ Enter { _rx : self }
77
+ }
78
+ }
79
+
80
+ // ===== impl Enter =====
81
+
82
+ impl < ' a , T > Drop for Enter < ' a , T > {
83
+ fn drop ( & mut self ) {
84
+ STORE . with ( |cell| cell. set ( ptr:: null_mut ( ) ) )
18
85
}
19
86
}
0 commit comments