@@ -20,12 +20,12 @@ use tracing::warn;
20
20
pub struct Subsystem < T : ControlSafe > {
21
21
value : RefCell < T > ,
22
22
tasks : RefCell < BinaryHeap < LockRequest > > ,
23
- current_priority : Cell < u32 > ,
23
+ current_priority : Cell < Priority > ,
24
24
current_cancellation : Rc < RefCell < Option < CancellationHandle > > > ,
25
25
}
26
26
27
27
struct LockRequest {
28
- priority : u32 ,
28
+ priority : Priority ,
29
29
waker : Weak < Cell < Option < Waker > > > ,
30
30
}
31
31
@@ -71,15 +71,20 @@ impl<T: ControlSafe> Subsystem<T> {
71
71
Self {
72
72
value : RefCell :: new ( value) ,
73
73
tasks : RefCell :: new ( BinaryHeap :: new ( ) ) ,
74
- current_priority : Cell :: new ( 0 ) ,
74
+ current_priority : Cell :: new ( Priority {
75
+ value : 0 ,
76
+ should_cancel : false ,
77
+ } ) ,
75
78
current_cancellation,
76
79
}
77
80
}
78
81
79
82
/// Lock the subsystem with the given priority. This will cancel the scope of any locks that have a lower priority.
80
- pub fn lock ( & self , priority : u32 ) -> LockFuture < ' _ , T > {
83
+ pub fn lock < P : AsPriority > ( & self , priority : P ) -> LockFuture < ' _ , T > {
81
84
let waker = Rc :: new ( Cell :: new ( None ) ) ;
82
85
86
+ let priority = priority. as_priority ( ) ;
87
+
83
88
self . tasks . borrow_mut ( ) . push ( LockRequest {
84
89
priority,
85
90
waker : Rc :: downgrade ( & waker) ,
@@ -97,7 +102,7 @@ impl<T: ControlSafe> Subsystem<T> {
97
102
pub struct LockFuture < ' a , T : ControlSafe > {
98
103
lock : & ' a Subsystem < T > ,
99
104
waker : Rc < Cell < Option < Waker > > > ,
100
- priority : u32 ,
105
+ priority : Priority ,
101
106
}
102
107
103
108
fn peek < ' a > ( val : & mut RefMut < ' a , BinaryHeap < LockRequest > > ) -> Option < Rc < Cell < Option < Waker > > > > {
@@ -148,7 +153,7 @@ impl<'a, T: ControlSafe> Future for LockFuture<'a, T> {
148
153
guard,
149
154
} )
150
155
} else {
151
- if inner. lock . current_priority . get ( ) <= inner . priority {
156
+ if inner. priority . is_higher ( & inner . lock . current_priority . get ( ) ) {
152
157
if let Some ( handle) = inner. lock . current_cancellation . borrow ( ) . as_ref ( ) {
153
158
handle. cancel ( ) ;
154
159
}
@@ -191,3 +196,57 @@ impl<'a, T: ControlSafe> Drop for LockGuard<'a, T> {
191
196
}
192
197
}
193
198
}
199
+
200
+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
201
+ pub struct Priority {
202
+ value : u32 ,
203
+ /// If this is set to true, it will cancel tasks with the same or a lower priority value
204
+ should_cancel : bool ,
205
+ }
206
+
207
+ impl Priority {
208
+ fn is_higher ( & self , other : & Priority ) -> bool {
209
+ ( self . value > other. value ) || ( self . should_cancel && self . value >= other. value )
210
+ }
211
+ }
212
+
213
+ pub trait AsPriority {
214
+ fn as_priority ( self ) -> Priority ;
215
+ }
216
+
217
+ impl AsPriority for Priority {
218
+ fn as_priority ( self ) -> Priority {
219
+ self
220
+ }
221
+ }
222
+
223
+ impl AsPriority for u32 {
224
+ fn as_priority ( self ) -> Priority {
225
+ Priority {
226
+ value : self ,
227
+ should_cancel : false ,
228
+ }
229
+ }
230
+ }
231
+
232
+ pub trait PriorityExt {
233
+ fn cancelling ( self ) -> Priority ;
234
+ }
235
+
236
+ impl PriorityExt for Priority {
237
+ fn cancelling ( self ) -> Priority {
238
+ Self {
239
+ should_cancel : true ,
240
+ value : self . value ,
241
+ }
242
+ }
243
+ }
244
+
245
+ impl PriorityExt for u32 {
246
+ fn cancelling ( self ) -> Priority {
247
+ Priority {
248
+ value : self ,
249
+ should_cancel : true ,
250
+ }
251
+ }
252
+ }
0 commit comments