1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use std::future::Future;
use std::io;
use std::mem::ManuallyDrop;
use std::pin::Pin;
use std::task::{Context, Poll};

use futures_core::ready;

use crate::{Event, Drive, Ring};

/// A [`Future`] representing an event submitted to io-uring
pub struct Submission<E: Event, D: Drive> {
    ring: Ring<D>,
    event: Option<ManuallyDrop<E>>,
}

impl<E: Event, D: Drive> Submission<E, D> {
    /// Construct a new submission from an event and a driver.
    pub fn new(event: E, driver: D) -> Submission<E, D> {
        Submission {
            ring: Ring::new(driver),
            event: Some(ManuallyDrop::new(event)),
        }
    }

    /// Access the driver this submission is using
    pub fn driver(&self) -> &D {
        self.ring.driver()
    }

    fn split(self: Pin<&mut Self>) -> (Pin<&mut Ring<D>>, &mut Option<ManuallyDrop<E>>) {
        unsafe {
            let this = Pin::get_unchecked_mut(self);
            (Pin::new_unchecked(&mut this.ring), &mut this.event)
        }
    }
}

impl<E, D> Future for Submission<E, D> where
    E: Event,
    D: Drive,
{
    type Output = (E, io::Result<usize>);

    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let (ring, event) = self.split();

        let result = if let Some(event) = event {
            ready!(ring.poll(ctx, event.is_eager(), |sqe| unsafe { event.prepare(sqe) }))
        } else {
            panic!("polled Submission after completion")
        };

        Poll::Ready((ManuallyDrop::into_inner(event.take().unwrap()), result))
    }
}


impl<E: Event, D: Drive> Drop for Submission<E, D> {
    fn drop(&mut self) {
        if let Some(event) = &mut self.event {
            let cancellation = unsafe { Event::cancel(event) };
            self.ring.cancel(cancellation);
        }
    }
}