aboutsummaryrefslogtreecommitdiff
path: root/embassy-std
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2020-12-28 03:40:28 +0100
committerDario Nieuwenhuis <[email protected]>2020-12-28 03:41:40 +0100
commit4a7344cb6f33bc6acdb982b7c180e0da81ad2710 (patch)
tree289c869ccd6cb953d554fc085dfed388649e0b2b /embassy-std
parent32c67381df48979f6cf3c188b0dec447d1935d12 (diff)
Add embassy-std crate with glue to run embassy on std.
Diffstat (limited to 'embassy-std')
-rw-r--r--embassy-std/Cargo.toml10
-rw-r--r--embassy-std/src/lib.rs95
2 files changed, 105 insertions, 0 deletions
diff --git a/embassy-std/Cargo.toml b/embassy-std/Cargo.toml
new file mode 100644
index 000000000..2a8028137
--- /dev/null
+++ b/embassy-std/Cargo.toml
@@ -0,0 +1,10 @@
1[package]
2name = "embassy-std"
3version = "0.1.0"
4authors = ["Dario Nieuwenhuis <[email protected]>"]
5edition = "2018"
6
7[dependencies]
8embassy = { version = "0.1.0", path = "../embassy", features = ["std"] }
9lazy_static = "1.4.0"
10rand_core = { version = "0.6.0", features = ["std"] }
diff --git a/embassy-std/src/lib.rs b/embassy-std/src/lib.rs
new file mode 100644
index 000000000..2fb814b4d
--- /dev/null
+++ b/embassy-std/src/lib.rs
@@ -0,0 +1,95 @@
1use embassy::executor::Executor;
2use embassy::time::TICKS_PER_SECOND;
3use embassy::time::{Alarm, Clock};
4use embassy::util::Forever;
5use rand_core::{OsRng, RngCore};
6use std::mem::MaybeUninit;
7use std::sync::{Condvar, Mutex};
8use std::time::{Duration as StdDuration, Instant as StdInstant};
9
10static mut CLOCK_ZERO: MaybeUninit<StdInstant> = MaybeUninit::uninit();
11struct StdClock;
12impl Clock for StdClock {
13 fn now(&self) -> u64 {
14 let zero = unsafe { CLOCK_ZERO.as_ptr().read() };
15 let dur = StdInstant::now().duration_since(zero);
16 dur.as_secs() * (TICKS_PER_SECOND as u64)
17 + (dur.subsec_nanos() as u64) * (TICKS_PER_SECOND as u64) / 1_000_000_000
18 }
19}
20
21struct StdRand;
22impl embassy::rand::Rand for StdRand {
23 fn rand(&self, buf: &mut [u8]) {
24 OsRng.fill_bytes(buf);
25 }
26}
27
28static mut ALARM_AT: u64 = u64::MAX;
29
30pub struct StdAlarm;
31impl Alarm for StdAlarm {
32 fn set_callback(&self, _callback: fn()) {}
33 fn set(&self, timestamp: u64) {
34 unsafe { ALARM_AT = timestamp }
35 }
36
37 fn clear(&self) {
38 unsafe { ALARM_AT = u64::MAX }
39 }
40}
41
42static EXECUTOR: Forever<Executor> = Forever::new();
43
44lazy_static::lazy_static! {
45 static ref MUTEX: Mutex<bool> = Mutex::new(false);
46 static ref CONDVAR: Condvar = Condvar::new();
47}
48
49pub fn init() -> &'static Executor {
50 unsafe {
51 CLOCK_ZERO.as_mut_ptr().write(StdInstant::now());
52 embassy::time::set_clock(&StdClock);
53 embassy::rand::set_rand(&StdRand);
54
55 EXECUTOR.put(Executor::new_with_alarm(&StdAlarm, || {
56 let mut signaled = MUTEX.lock().unwrap();
57 *signaled = true;
58 CONDVAR.notify_one();
59 }))
60 }
61}
62
63pub fn run(executor: &'static Executor) -> ! {
64 unsafe {
65 loop {
66 executor.run();
67
68 let mut signaled = MUTEX.lock().unwrap();
69 while !*signaled {
70 let alarm_at = ALARM_AT;
71 if alarm_at == u64::MAX {
72 signaled = CONDVAR.wait(signaled).unwrap();
73 } else {
74 let now = StdClock.now();
75 if now >= alarm_at {
76 break;
77 }
78
79 let left = alarm_at - now;
80 let dur = StdDuration::new(
81 left / (TICKS_PER_SECOND as u64),
82 (left % (TICKS_PER_SECOND as u64) * 1_000_000_000
83 / (TICKS_PER_SECOND as u64)) as u32,
84 );
85 let (signaled2, timeout) = CONDVAR.wait_timeout(signaled, dur).unwrap();
86 signaled = signaled2;
87 if timeout.timed_out() {
88 break;
89 }
90 }
91 }
92 *signaled = false;
93 }
94 }
95}