|
29 | 29 | //! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h)
|
30 | 30 |
|
31 | 31 | use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};
|
| 32 | +use alloc::alloc::AllocError; |
32 | 33 | use alloc::boxed::Box;
|
33 | 34 | use core::marker::PhantomData;
|
34 | 35 | use core::pin::Pin;
|
@@ -96,6 +97,44 @@ impl Queue {
|
96 | 97 | })
|
97 | 98 | }
|
98 | 99 | }
|
| 100 | + |
| 101 | + /// Tries to spawn the given function or closure as a work item. |
| 102 | + /// |
| 103 | + /// This method can fail because it allocates memory to store the work item. |
| 104 | + pub fn try_spawn<T: 'static + Send + FnOnce()>(&self, func: T) -> Result<(), AllocError> { |
| 105 | + let init = pin_init!(ClosureWork { |
| 106 | + work <- new_work!("Queue::try_spawn"), |
| 107 | + func: Some(func), |
| 108 | + }); |
| 109 | + |
| 110 | + self.enqueue(Box::pin_init(init).map_err(|_| AllocError)?); |
| 111 | + Ok(()) |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +/// A helper type used in `try_spawn`. |
| 116 | +#[pin_data] |
| 117 | +struct ClosureWork<T> { |
| 118 | + #[pin] |
| 119 | + work: Work<ClosureWork<T>>, |
| 120 | + func: Option<T>, |
| 121 | +} |
| 122 | + |
| 123 | +impl<T> ClosureWork<T> { |
| 124 | + fn project(self: Pin<&mut Self>) -> &mut Option<T> { |
| 125 | + // SAFETY: The `func` field is not structurally pinned. |
| 126 | + unsafe { &mut self.get_unchecked_mut().func } |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +impl<T: FnOnce()> WorkItem for ClosureWork<T> { |
| 131 | + type Pointer = Pin<Box<Self>>; |
| 132 | + |
| 133 | + fn run(mut this: Pin<Box<Self>>) { |
| 134 | + if let Some(func) = this.as_mut().project().take() { |
| 135 | + (func)() |
| 136 | + } |
| 137 | + } |
99 | 138 | }
|
100 | 139 |
|
101 | 140 | /// A raw work item.
|
@@ -365,6 +404,10 @@ macro_rules! impl_has_work {
|
365 | 404 | )*};
|
366 | 405 | }
|
367 | 406 |
|
| 407 | +impl_has_work! { |
| 408 | + impl<T> HasWork<Self> for ClosureWork<T> { self.work } |
| 409 | +} |
| 410 | + |
368 | 411 | unsafe impl<T, const ID: u64> WorkItemPointer<ID> for Arc<T>
|
369 | 412 | where
|
370 | 413 | T: WorkItem<ID, Pointer = Self>,
|
|
0 commit comments