1
- use std:: {
2
- cell:: { Cell , RefCell } ,
3
- time:: { Duration , Instant } ,
4
- } ;
1
+ use std:: time:: { Duration , Instant } ;
5
2
3
+ use async_trait:: async_trait;
6
4
use thiserror:: Error ;
7
- use tokio:: sync:: mpsc:: { Receiver , Sender } ;
5
+ use tokio:: sync:: {
6
+ mpsc:: { Receiver , Sender } ,
7
+ Mutex ,
8
+ } ;
8
9
9
10
use crate :: {
10
11
image:: { RawImage , RawImageError } ,
@@ -18,12 +19,16 @@ pub enum ControlMessage {
18
19
Abort ,
19
20
}
20
21
22
+ struct InstanceMethodsData {
23
+ crx : Receiver < ControlMessage > ,
24
+ aborted : bool ,
25
+ }
26
+
21
27
pub struct InstanceMethods {
22
28
tx : Sender < EffectMessageKind > ,
23
- crx : RefCell < Receiver < ControlMessage > > ,
24
29
led_count : usize ,
25
30
deadline : Option < Instant > ,
26
- aborted : Cell < bool > ,
31
+ data : Mutex < InstanceMethodsData > ,
27
32
}
28
33
29
34
impl InstanceMethods {
@@ -35,23 +40,26 @@ impl InstanceMethods {
35
40
) -> Self {
36
41
Self {
37
42
tx,
38
- crx : crx. into ( ) ,
39
43
led_count,
40
44
deadline : duration. map ( |d| Instant :: now ( ) + d) ,
41
- aborted : false . into ( ) ,
45
+ data : Mutex :: new ( InstanceMethodsData {
46
+ crx : crx. into ( ) ,
47
+ aborted : false . into ( ) ,
48
+ } ) ,
42
49
}
43
50
}
44
51
45
- fn completed ( & self ) -> bool {
46
- self . aborted . get ( ) || self . deadline . map ( |d| Instant :: now ( ) > d) . unwrap_or ( false )
52
+ fn completed ( & self , data : & InstanceMethodsData ) -> bool {
53
+ data . aborted || self . deadline . map ( |d| Instant :: now ( ) > d) . unwrap_or ( false )
47
54
}
48
55
49
56
/// Returns true if the should abort
50
- fn poll_control ( & self ) -> Result < ( ) , RuntimeMethodError > {
51
- match self . crx . borrow_mut ( ) . try_recv ( ) {
57
+ async fn poll_control ( & self ) -> Result < ( ) , RuntimeMethodError > {
58
+ let mut data = self . data . lock ( ) . await ;
59
+ match data. crx . try_recv ( ) {
52
60
Ok ( m) => match m {
53
61
ControlMessage :: Abort => {
54
- self . aborted . set ( true ) ;
62
+ data . aborted = true ;
55
63
return Err ( RuntimeMethodError :: EffectAborted ) ;
56
64
}
57
65
} ,
@@ -62,74 +70,90 @@ impl InstanceMethods {
62
70
}
63
71
tokio:: sync:: mpsc:: error:: TryRecvError :: Disconnected => {
64
72
// We were disconnected
65
- self . aborted . set ( true ) ;
73
+ data . aborted = true ;
66
74
return Err ( RuntimeMethodError :: EffectAborted ) ;
67
75
}
68
76
}
69
77
}
70
78
}
71
79
72
- if self . completed ( ) {
80
+ if self . completed ( & * data ) {
73
81
Err ( RuntimeMethodError :: EffectAborted )
74
82
} else {
75
83
Ok ( ( ) )
76
84
}
77
85
}
78
86
79
- fn wrap_result < T , E : Into < RuntimeMethodError > > (
87
+ async fn wrap_result < T , E : Into < RuntimeMethodError > > (
80
88
& self ,
81
89
res : Result < T , E > ,
82
90
) -> Result < T , RuntimeMethodError > {
83
91
match res {
84
92
Ok ( t) => Ok ( t) ,
85
93
Err ( err) => {
86
94
// TODO: Log error?
87
- self . aborted . set ( true ) ;
95
+ self . data . lock ( ) . await . aborted = true ;
88
96
Err ( err. into ( ) )
89
97
}
90
98
}
91
99
}
92
100
}
93
101
102
+ #[ async_trait]
94
103
impl RuntimeMethods for InstanceMethods {
95
104
fn get_led_count ( & self ) -> usize {
96
105
self . led_count
97
106
}
98
107
99
- fn abort ( & self ) -> bool {
100
- self . poll_control ( ) . is_err ( )
108
+ async fn abort ( & self ) -> bool {
109
+ self . poll_control ( ) . await . is_err ( )
101
110
}
102
111
103
- fn set_color ( & self , color : crate :: models:: Color ) -> Result < ( ) , RuntimeMethodError > {
104
- self . poll_control ( ) ?;
112
+ async fn set_color ( & self , color : crate :: models:: Color ) -> Result < ( ) , RuntimeMethodError > {
113
+ self . poll_control ( ) . await ?;
105
114
106
- self . wrap_result ( self . tx . blocking_send ( EffectMessageKind :: SetColor { color } ) )
115
+ self . wrap_result ( self . tx . send ( EffectMessageKind :: SetColor { color } ) . await )
116
+ . await
107
117
}
108
118
109
- fn set_led_colors ( & self , colors : Vec < crate :: models:: Color > ) -> Result < ( ) , RuntimeMethodError > {
110
- self . poll_control ( ) ?;
111
-
112
- self . wrap_result ( self . tx . blocking_send ( EffectMessageKind :: SetLedColors {
113
- colors : colors. into ( ) ,
114
- } ) )
119
+ async fn set_led_colors (
120
+ & self ,
121
+ colors : Vec < crate :: models:: Color > ,
122
+ ) -> Result < ( ) , RuntimeMethodError > {
123
+ self . poll_control ( ) . await ?;
124
+
125
+ self . wrap_result (
126
+ self . tx
127
+ . send ( EffectMessageKind :: SetLedColors {
128
+ colors : colors. into ( ) ,
129
+ } )
130
+ . await ,
131
+ )
132
+ . await
115
133
}
116
134
117
- fn set_image ( & self , image : RawImage ) -> Result < ( ) , RuntimeMethodError > {
118
- self . poll_control ( ) ?;
119
-
120
- self . wrap_result ( self . tx . blocking_send ( EffectMessageKind :: SetImage {
121
- image : image. into ( ) ,
122
- } ) )
135
+ async fn set_image ( & self , image : RawImage ) -> Result < ( ) , RuntimeMethodError > {
136
+ self . poll_control ( ) . await ?;
137
+
138
+ self . wrap_result (
139
+ self . tx
140
+ . send ( EffectMessageKind :: SetImage {
141
+ image : image. into ( ) ,
142
+ } )
143
+ . await ,
144
+ )
145
+ . await
123
146
}
124
147
}
125
148
126
- pub trait RuntimeMethods {
149
+ #[ async_trait]
150
+ pub trait RuntimeMethods : Send {
127
151
fn get_led_count ( & self ) -> usize ;
128
- fn abort ( & self ) -> bool ;
152
+ async fn abort ( & self ) -> bool ;
129
153
130
- fn set_color ( & self , color : Color ) -> Result < ( ) , RuntimeMethodError > ;
131
- fn set_led_colors ( & self , colors : Vec < Color > ) -> Result < ( ) , RuntimeMethodError > ;
132
- fn set_image ( & self , image : RawImage ) -> Result < ( ) , RuntimeMethodError > ;
154
+ async fn set_color ( & self , color : Color ) -> Result < ( ) , RuntimeMethodError > ;
155
+ async fn set_led_colors ( & self , colors : Vec < Color > ) -> Result < ( ) , RuntimeMethodError > ;
156
+ async fn set_image ( & self , image : RawImage ) -> Result < ( ) , RuntimeMethodError > ;
133
157
}
134
158
135
159
#[ derive( Debug , Error ) ]
0 commit comments