Skip to main content

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 crate::io::IoError;
32use std::future::Future;
33use std::pin::Pin;
34use std::task::Context;
35use std::task::Poll;
36use std::task::ready;
37
38/// Token to return in [`IoResult::Defer`](super::IoResult::Defer) for deferred
39/// IOs.
40///
41/// Create with [`defer_read`] or [`defer_write`].
42#[derive(Debug)]
43pub struct DeferredToken {
44    is_read: bool,
45    recv: mesh::OneshotReceiver<Result<(u64, usize), IoError>>,
46}
47
48impl DeferredToken {
49    /// Polls the deferred token for the results of a read operation.
50    ///
51    /// Copies the results into `bytes`.
52    ///
53    /// Panics if the deferred token was for a write operation.
54    pub fn poll_read(
55        &mut self,
56        cx: &mut Context<'_>,
57        bytes: &mut [u8],
58    ) -> Poll<Result<(), IoError>> {
59        assert!(self.is_read, "defer type mismatch");
60        let r = ready!(Pin::new(&mut self.recv).poll(cx));
61        match r {
62            Ok(Ok((v, len))) => {
63                assert_eq!(len, bytes.len(), "defer size mismatch");
64                bytes.copy_from_slice(&v.to_ne_bytes()[..len]);
65                Poll::Ready(Ok(()))
66            }
67            Ok(Err(e)) => Poll::Ready(Err(e)),
68            Err(_) => Poll::Ready(Err(IoError::NoResponse)),
69        }
70    }
71
72    /// Polls the deferred token for the results of a write operation.
73    ///
74    /// Panics if the deferred token was for a read operation.
75    pub fn poll_write(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), IoError>> {
76        assert!(!self.is_read, "defer type mismatch");
77        let r = ready!(Pin::new(&mut self.recv).poll(cx));
78        match r {
79            Ok(Ok(_)) => Poll::Ready(Ok(())),
80            Ok(Err(e)) => Poll::Ready(Err(e)),
81            Err(_) => Poll::Ready(Err(IoError::NoResponse)),
82        }
83    }
84
85    /// Returns a future that waits for the deferred write to complete.
86    ///
87    /// Panics if the deferred token was for a read operation.
88    pub async fn write_future(mut self) -> Result<(), IoError> {
89        std::future::poll_fn(|cx| self.poll_write(cx)).await
90    }
91
92    /// Returns a future that waits for the deferred read to complete, and
93    /// copies the results into `bytes`.
94    ///
95    /// Panics if the deferred token was for a write operation.
96    pub async fn read_future(mut self, bytes: &mut [u8]) -> Result<(), IoError> {
97        std::future::poll_fn(|cx| self.poll_read(cx, bytes)).await
98    }
99}
100
101/// A deferred read operation.
102#[derive(Debug)]
103pub struct DeferredRead {
104    send: mesh::OneshotSender<Result<(u64, usize), IoError>>,
105}
106
107impl DeferredRead {
108    /// Completes the read operation with the specified data.
109    pub fn complete(self, bytes: &[u8]) {
110        let mut v = [0; 8];
111        v[..bytes.len()].copy_from_slice(bytes);
112        self.send.send(Ok((u64::from_ne_bytes(v), bytes.len())));
113    }
114
115    /// Completes the read operation with an error.
116    pub fn complete_error(self, error: IoError) {
117        self.send.send(Err(error));
118    }
119}
120
121/// A deferred write operation.
122#[derive(Debug)]
123pub struct DeferredWrite {
124    send: mesh::OneshotSender<Result<(u64, usize), IoError>>,
125}
126
127impl DeferredWrite {
128    /// Completes the write operation.
129    pub fn complete(self) {
130        self.send.send(Ok((0, 0)));
131    }
132
133    /// Completes the write operation with an error.
134    pub fn complete_error(self, error: IoError) {
135        self.send.send(Err(error));
136    }
137}
138
139/// Creates a deferred IO read operation.
140pub fn defer_read() -> (DeferredRead, DeferredToken) {
141    let (send, recv) = mesh::oneshot();
142    (
143        DeferredRead { send },
144        DeferredToken {
145            is_read: true,
146            recv,
147        },
148    )
149}
150
151/// Creates a deferred IO write operation.
152pub fn defer_write() -> (DeferredWrite, DeferredToken) {
153    let (send, recv) = mesh::oneshot();
154    (
155        DeferredWrite { send },
156        DeferredToken {
157            is_read: false,
158            recv,
159        },
160    )
161}