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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Support for deferred IO, used when an IO can't be completed synchronously.
//!
//! Example:
//!
//! ```rust
//! # use chipset_device::io::{IoResult, deferred::{DeferredRead, defer_read}};
//! # use std::task::Context;
//! struct Device {
//! deferred: Option<DeferredRead>,
//! }
//!
//! impl Device {
//! fn read_handler(&mut self, data: &mut [u8]) -> IoResult {
//! // Defer this request to later.
//! let (deferred, token) = defer_read();
//! IoResult::Defer(token.into())
//! }
//!
//! fn poll_device(&mut self, _cx: &mut Context<'_>) {
//! // The data is now available, complete the request.
//! if let Some(deferred) = self.deferred.take() {
//! deferred.complete(&[123]);
//! }
//! }
//! }
//! ```
use std::future::Future;
use std::pin::Pin;
use std::task::ready;
use std::task::Context;
use std::task::Poll;
/// Token to return in [`IoResult::Defer`](super::IoResult::Defer) for deferred
/// IOs.
///
/// Create with [`defer_read`] or [`defer_write`].
#[derive(Debug)]
pub struct DeferredToken {
is_read: bool,
recv: mesh::OneshotReceiver<(u64, usize)>,
}
impl DeferredToken {
/// Polls the deferred token for the results of a read operation.
///
/// Copies the results into `bytes`.
///
/// Panics if the deferred token was for a write operation.
pub fn poll_read(
&mut self,
cx: &mut Context<'_>,
bytes: &mut [u8],
) -> Poll<Result<(), mesh::RecvError>> {
assert!(self.is_read, "defer type mismatch");
let (v, len) = ready!(Pin::new(&mut self.recv).poll(cx))?;
assert_eq!(len, bytes.len(), "defer size mismatch");
bytes.copy_from_slice(&v.to_ne_bytes()[..len]);
Poll::Ready(Ok(()))
}
/// Polls the deferred token for the results of a write operation.
///
/// Panics if the deferred token was for a read operation.
pub fn poll_write(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), mesh::RecvError>> {
assert!(!self.is_read, "defer type mismatch");
ready!(Pin::new(&mut self.recv).poll(cx))?;
Poll::Ready(Ok(()))
}
}
/// A deferred read operation.
#[derive(Debug)]
pub struct DeferredRead {
send: mesh::OneshotSender<(u64, usize)>,
}
impl DeferredRead {
/// Completes the read operation with the specified data.
pub fn complete(self, bytes: &[u8]) {
let mut v = [0; 8];
v[..bytes.len()].copy_from_slice(bytes);
self.send.send((u64::from_ne_bytes(v), bytes.len()));
}
}
/// A deferred write operation.
#[derive(Debug)]
pub struct DeferredWrite {
send: mesh::OneshotSender<(u64, usize)>,
}
impl DeferredWrite {
/// Completes the write operation.
pub fn complete(self) {
self.send.send((0, 0));
}
}
/// Creates a deferred IO read operation.
pub fn defer_read() -> (DeferredRead, DeferredToken) {
let (send, recv) = mesh::oneshot();
(
DeferredRead { send },
DeferredToken {
is_read: true,
recv,
},
)
}
/// Creates a deferred IO write operation.
pub fn defer_write() -> (DeferredWrite, DeferredToken) {
let (send, recv) = mesh::oneshot();
(
DeferredWrite { send },
DeferredToken {
is_read: false,
recv,
},
)
}