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
//! # Input
//! What a task can run with when nothing gives it an input, and
//! which values a task spawned with `wait_for` can wait for
use crate::{
futures::task::{Nothing, Task},
modules::mailbox::Mailbox,
};
/// Stops the traits here being implemented or called outside the
/// crate
pub(crate) mod sealed {
/// Implemented for every input a task can make up for itself
pub trait Sealed {}
/// Proof a call came from inside the crate
///
/// Nothing outside can name it, so nothing outside can make up
/// an input or hand one to a task
pub struct Token(pub(crate) ());
}
pub(crate) use sealed::Token;
/// An input a task can run with when nothing gives it one
///
/// `()` for a compute whose closure takes nothing, and
/// [`Nothing`] for every other task
#[allow(private_bounds, private_interfaces)]
pub trait Standalone: sealed::Sealed + Sized {
/// The value a run gets when nothing gave it one
#[doc(hidden)]
fn standalone(token: sealed::Token) -> Self;
}
impl sealed::Sealed for () {}
impl sealed::Sealed for Nothing {}
impl Standalone for () {
#[inline(always)]
fn standalone(_token: sealed::Token) -> Self {}
}
impl Standalone for Nothing {
#[inline(always)]
fn standalone(_token: sealed::Token) -> Self {
Nothing(())
}
}
/// Marks a wait whose value the task runs with
pub struct Use;
/// Marks a wait whose value is dropped, for a task that takes no
/// input and only waits for the give
pub struct Ignore;
/// An input a task can be given values of `T` for
///
/// `M` is worked out by the compiler and never written: [`Use`]
/// when `T` is the input itself, and [`Ignore`] when the task
/// takes [`Nothing`] and only waits
#[diagnostic::on_unimplemented(
message = "a task that takes `{Self}` can't wait for `{T}`",
label = "waits for `{T}`",
note = "a compute can take `_: {T}` to wait for it without using the value"
)]
#[allow(private_bounds, private_interfaces)]
pub trait Receives<T, M>: Sized {
/// Hands the task the latest value given, for a run about to
/// start
#[doc(hidden)]
fn deliver<F>(token: sealed::Token, task: &mut F, mailbox: &Mailbox<T>)
where
F: Task<Input = Self>;
}
impl<T> Receives<T, Ignore> for Nothing {
#[inline(always)]
fn deliver<F>(_token: sealed::Token, _task: &mut F, _mailbox: &Mailbox<T>)
where
F: Task<Input = Self>,
{
}
}
impl<V> Receives<V, Use> for V
where
V: Clone,
{
#[inline(always)]
fn deliver<F>(token: sealed::Token, task: &mut F, mailbox: &Mailbox<V>)
where
F: Task<Input = Self>,
{
if let Some(value) = mailbox.latest() {
task.give(token, value);
}
}
}
/// The input a task makes up for itself
#[inline(always)]
pub(crate) fn standalone<V>() -> V
where
V: Standalone,
{
V::standalone(token())
}
/// Proof a call comes from inside the crate
#[inline(always)]
pub(crate) fn token() -> sealed::Token {
sealed::Token(())
}