chipset_device/io/
deferred.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Support for deferred IO, used when an IO can't be completed synchronously.
5//!
6//! Example:
7//!
8//! ```rust
9//! # use chipset_device::io::{IoResult, deferred::{DeferredRead, defer_read}};
10//! # use std::task::Context;
11//! struct Device {
12//!     deferred: Option<DeferredRead>,
13//! }
14//!
15//! impl Device {
16//!     fn read_handler(&mut self, data: &mut [u8]) -> IoResult {
17//!         // Defer this request to later.
18//!         let (deferred, token) = defer_read();
19//!         IoResult::Defer(token.into())
20//!     }
21//!
22//!     fn poll_device(&mut self, _cx: &mut Context<'_>) {
23//!         // The data is now available, complete the request.
24//!         if let Some(deferred) = self.deferred.take() {
25//!             deferred.complete(&[123]);
26//!         }
27//!     }
28//! }
29//! ```
30
31use std::future::Future;
32use std::pin::Pin;
33use std::task::Context;
34use std::task::Poll;
35use std::task::ready;
36
37/// Token to return in [`IoResult::Defer`](super::IoResult::Defer) for deferred
38/// IOs.
39///
40/// Create with [`defer_read`] or [`defer_write`].
41#[derive(Debug)]
42pub struct DeferredToken {
43    is_read: bool,
44    recv: mesh::OneshotReceiver<(u64, usize)>,
45}
46
47impl DeferredToken {
48    /// Polls the deferred token for the results of a read operation.
49    ///
50    /// Copies the results into `bytes`.
51    ///
52    /// Panics if the deferred token was for a write operation.
53    pub fn poll_read(
54        &mut self,
55        cx: &mut Context<'_>,
56        bytes: &mut [u8],
57    ) -> Poll<Result<(), mesh::RecvError>> {
58        assert!(self.is_read, "defer type mismatch");
59        let (v, len) = ready!(Pin::new(&mut self.recv).poll(cx))?;
60        assert_eq!(len, bytes.len(), "defer size mismatch");
61        bytes.copy_from_slice(&v.to_ne_bytes()[..len]);
62        Poll::Ready(Ok(()))
63    }
64
65    /// Polls the deferred token for the results of a write operation.
66    ///
67    /// Panics if the deferred token was for a read operation.
68    pub fn poll_write(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), mesh::RecvError>> {
69        assert!(!self.is_read, "defer type mismatch");
70        ready!(Pin::new(&mut self.recv).poll(cx))?;
71        Poll::Ready(Ok(()))
72    }
73}
74
75/// A deferred read operation.
76#[derive(Debug)]
77pub struct DeferredRead {
78    send: mesh::OneshotSender<(u64, usize)>,
79}
80
81impl DeferredRead {
82    /// Completes the read operation with the specified data.
83    pub fn complete(self, bytes: &[u8]) {
84        let mut v = [0; 8];
85        v[..bytes.len()].copy_from_slice(bytes);
86        self.send.send((u64::from_ne_bytes(v), bytes.len()));
87    }
88}
89
90/// A deferred write operation.
91#[derive(Debug)]
92pub struct DeferredWrite {
93    send: mesh::OneshotSender<(u64, usize)>,
94}
95
96impl DeferredWrite {
97    /// Completes the write operation.
98    pub fn complete(self) {
99        self.send.send((0, 0));
100    }
101}
102
103/// Creates a deferred IO read operation.
104pub fn defer_read() -> (DeferredRead, DeferredToken) {
105    let (send, recv) = mesh::oneshot();
106    (
107        DeferredRead { send },
108        DeferredToken {
109            is_read: true,
110            recv,
111        },
112    )
113}
114
115/// Creates a deferred IO write operation.
116pub fn defer_write() -> (DeferredWrite, DeferredToken) {
117    let (send, recv) = mesh::oneshot();
118    (
119        DeferredWrite { send },
120        DeferredToken {
121            is_read: false,
122            recv,
123        },
124    )
125}