sim_lib_control/async.rs
1use sim_kernel::Ref;
2
3/// Outcome of polling an [`AsyncTask`]: not yet complete, or a ready result.
4#[derive(Clone, Debug, PartialEq, Eq)]
5pub enum AsyncPoll {
6 /// The task has not yet reached its ready point and must be polled again.
7 Pending,
8 /// The task completed, carrying its result [`Ref`].
9 Ready(Ref),
10}
11
12/// A deterministic async task that resolves after a fixed number of polls.
13///
14/// The simplest control organ in this crate: it models the poll-to-completion
15/// surface of asynchronous behavior without a real executor, so the
16/// control-policy contracts can be exercised deterministically.
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct AsyncTask {
19 result: Ref,
20 pending_polls: usize,
21 polls: usize,
22}
23
24impl AsyncTask {
25 /// Builds a task that reports [`AsyncPoll::Pending`] for `pending_polls`
26 /// polls, then yields `result`.
27 pub fn ready_after(pending_polls: usize, result: Ref) -> Self {
28 Self {
29 result,
30 pending_polls,
31 polls: 0,
32 }
33 }
34
35 /// Advances the task one step, returning [`AsyncPoll::Pending`] until the
36 /// pending count is exhausted and [`AsyncPoll::Ready`] thereafter.
37 pub fn poll(&mut self) -> AsyncPoll {
38 if self.polls < self.pending_polls {
39 self.polls += 1;
40 return AsyncPoll::Pending;
41 }
42 AsyncPoll::Ready(self.result.clone())
43 }
44}