Skip to content

Commit 582b3c7

Browse files
committed
Use custom priority in subsystem
1 parent 2218b9d commit 582b3c7

File tree

1 file changed

+65
-6
lines changed

1 file changed

+65
-6
lines changed

crates/utils/src/subsystem.rs

+65-6
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ use tracing::warn;
2020
pub struct Subsystem<T: ControlSafe> {
2121
value: RefCell<T>,
2222
tasks: RefCell<BinaryHeap<LockRequest>>,
23-
current_priority: Cell<u32>,
23+
current_priority: Cell<Priority>,
2424
current_cancellation: Rc<RefCell<Option<CancellationHandle>>>,
2525
}
2626

2727
struct LockRequest {
28-
priority: u32,
28+
priority: Priority,
2929
waker: Weak<Cell<Option<Waker>>>,
3030
}
3131

@@ -71,15 +71,20 @@ impl<T: ControlSafe> Subsystem<T> {
7171
Self {
7272
value: RefCell::new(value),
7373
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+
}),
7578
current_cancellation,
7679
}
7780
}
7881

7982
/// 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> {
8184
let waker = Rc::new(Cell::new(None));
8285

86+
let priority = priority.as_priority();
87+
8388
self.tasks.borrow_mut().push(LockRequest {
8489
priority,
8590
waker: Rc::downgrade(&waker),
@@ -97,7 +102,7 @@ impl<T: ControlSafe> Subsystem<T> {
97102
pub struct LockFuture<'a, T: ControlSafe> {
98103
lock: &'a Subsystem<T>,
99104
waker: Rc<Cell<Option<Waker>>>,
100-
priority: u32,
105+
priority: Priority,
101106
}
102107

103108
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> {
148153
guard,
149154
})
150155
} else {
151-
if inner.lock.current_priority.get() <= inner.priority {
156+
if inner.priority.is_higher(&inner.lock.current_priority.get()) {
152157
if let Some(handle) = inner.lock.current_cancellation.borrow().as_ref() {
153158
handle.cancel();
154159
}
@@ -191,3 +196,57 @@ impl<'a, T: ControlSafe> Drop for LockGuard<'a, T> {
191196
}
192197
}
193198
}
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

Comments
 (0)