1#![doc = include_str!("op.md")]
2
3use alloc::boxed::Box;
4use core::any::Any;
5use core::pin::Pin;
6use core::task::{Context, Poll};
7
8use crate::driver::{DriverHandle, OpId};
9
10pub unsafe trait Completable: 'static + Unpin {
14 type Output;
15 type Driver: DriverHandle;
16
17 fn complete(
22 self,
23 driver: &Self::Driver,
24 payload: <Self::Driver as DriverHandle>::Payload,
25 ) -> Self::Output;
26
27 fn complete_ext(
31 self,
32 driver: &Self::Driver,
33 payload: <Self::Driver as DriverHandle>::Payload,
34 ext: <Self::Driver as DriverHandle>::Ext,
35 ) -> Self::Output
36 where
37 Self: Sized,
38 {
39 _ = ext;
40 self.complete(driver, payload)
41 }
42
43 fn cancel(self, driver: &Self::Driver) -> Cancellation;
45}
46
47pub struct Cancellation(#[allow(dead_code)] Option<Box<dyn Any>>);
48
49impl Cancellation {
50 pub const fn noop() -> Self {
51 Self(None)
52 }
53
54 pub fn recycle<T: 'static>(resource: T) -> Self {
55 Self(Some(Box::new(resource)))
56 }
57}
58
59pub struct Op<T: Completable> {
60 driver: T::Driver,
61 id: OpId,
62 data: Option<T>,
63}
64
65impl<T: Completable> Op<T> {
66 pub fn new(driver: T::Driver, id: OpId, data: T) -> Self {
67 Self {
68 driver,
69 id,
70 data: Some(data),
71 }
72 }
73}
74
75impl<T: Completable> Future for Op<T> {
76 type Output = T::Output;
77 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
78 self.driver.get().poll(self.id, cx).map(|(p, ext)| {
79 self.data
80 .take()
81 .expect("invalid operation state")
82 .complete_ext(&self.driver, p, ext)
83 })
84 }
85}
86
87impl<T: Completable> Drop for Op<T> {
88 fn drop(&mut self) {
89 self.driver.get().remove(self.id, || {
90 self.data
91 .take()
92 .expect("invalid operation state")
93 .cancel(&self.driver)
94 })
95 }
96}