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}