aboutsummaryrefslogtreecommitdiff
path: root/embassy-std/src/lib.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-02-03 04:30:11 +0100
committerDario Nieuwenhuis <[email protected]>2021-02-03 04:30:11 +0100
commit4192e526298eb02c32727c765ae6d7ad4f933e2b (patch)
treea0f6363479da755ef5048efdc31c852af5d9d1a8 /embassy-std/src/lib.rs
parentedca627286fff5234cb91535a7d9627af0c0eeaf (diff)
Update embassy-std to new executor api
Diffstat (limited to 'embassy-std/src/lib.rs')
-rw-r--r--embassy-std/src/lib.rs132
1 files changed, 84 insertions, 48 deletions
diff --git a/embassy-std/src/lib.rs b/embassy-std/src/lib.rs
index 2fb814b4d..009ba028d 100644
--- a/embassy-std/src/lib.rs
+++ b/embassy-std/src/lib.rs
@@ -1,9 +1,10 @@
1use embassy::executor::Executor; 1use embassy::executor::{raw, Spawner};
2use embassy::time::TICKS_PER_SECOND; 2use embassy::time::TICKS_PER_SECOND;
3use embassy::time::{Alarm, Clock}; 3use embassy::time::{Alarm, Clock};
4use embassy::util::Forever;
5use rand_core::{OsRng, RngCore}; 4use rand_core::{OsRng, RngCore};
5use std::marker::PhantomData;
6use std::mem::MaybeUninit; 6use std::mem::MaybeUninit;
7use std::ptr;
7use std::sync::{Condvar, Mutex}; 8use std::sync::{Condvar, Mutex};
8use std::time::{Duration as StdDuration, Instant as StdInstant}; 9use std::time::{Duration as StdDuration, Instant as StdInstant};
9 10
@@ -29,7 +30,8 @@ static mut ALARM_AT: u64 = u64::MAX;
29 30
30pub struct StdAlarm; 31pub struct StdAlarm;
31impl Alarm for StdAlarm { 32impl Alarm for StdAlarm {
32 fn set_callback(&self, _callback: fn()) {} 33 fn set_callback(&self, _callback: fn(*mut ()), _ctx: *mut ()) {}
34
33 fn set(&self, timestamp: u64) { 35 fn set(&self, timestamp: u64) {
34 unsafe { ALARM_AT = timestamp } 36 unsafe { ALARM_AT = timestamp }
35 } 37 }
@@ -39,57 +41,91 @@ impl Alarm for StdAlarm {
39 } 41 }
40} 42}
41 43
42static EXECUTOR: Forever<Executor> = Forever::new(); 44struct Signaler {
43 45 mutex: Mutex<bool>,
44lazy_static::lazy_static! { 46 condvar: Condvar,
45 static ref MUTEX: Mutex<bool> = Mutex::new(false);
46 static ref CONDVAR: Condvar = Condvar::new();
47} 47}
48 48
49pub fn init() -> &'static Executor { 49impl Signaler {
50 unsafe { 50 fn new() -> Self {
51 CLOCK_ZERO.as_mut_ptr().write(StdInstant::now()); 51 Self {
52 embassy::time::set_clock(&StdClock); 52 mutex: Mutex::new(false),
53 embassy::rand::set_rand(&StdRand); 53 condvar: Condvar::new(),
54 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 } 55 }
61}
62 56
63pub fn run(executor: &'static Executor) -> ! { 57 fn wait(&self) {
64 unsafe { 58 let mut signaled = self.mutex.lock().unwrap();
65 loop { 59 while !*signaled {
66 executor.run(); 60 let alarm_at = unsafe { ALARM_AT };
67 61 if alarm_at == u64::MAX {
68 let mut signaled = MUTEX.lock().unwrap(); 62 signaled = self.condvar.wait(signaled).unwrap();
69 while !*signaled { 63 } else {
70 let alarm_at = ALARM_AT; 64 let now = StdClock.now();
71 if alarm_at == u64::MAX { 65 if now >= alarm_at {
72 signaled = CONDVAR.wait(signaled).unwrap(); 66 break;
73 } else { 67 }
74 let now = StdClock.now(); 68
75 if now >= alarm_at { 69 let left = alarm_at - now;
76 break; 70 let dur = StdDuration::new(
77 } 71 left / (TICKS_PER_SECOND as u64),
78 72 (left % (TICKS_PER_SECOND as u64) * 1_000_000_000 / (TICKS_PER_SECOND as u64))
79 let left = alarm_at - now; 73 as u32,
80 let dur = StdDuration::new( 74 );
81 left / (TICKS_PER_SECOND as u64), 75 let (signaled2, timeout) = self.condvar.wait_timeout(signaled, dur).unwrap();
82 (left % (TICKS_PER_SECOND as u64) * 1_000_000_000 76 signaled = signaled2;
83 / (TICKS_PER_SECOND as u64)) as u32, 77 if timeout.timed_out() {
84 ); 78 break;
85 let (signaled2, timeout) = CONDVAR.wait_timeout(signaled, dur).unwrap();
86 signaled = signaled2;
87 if timeout.timed_out() {
88 break;
89 }
90 } 79 }
91 } 80 }
92 *signaled = false; 81 }
82 *signaled = false;
83 }
84
85 fn signal(ctx: *mut ()) {
86 let this = unsafe { &*(ctx as *mut Self) };
87 let mut signaled = this.mutex.lock().unwrap();
88 *signaled = true;
89 this.condvar.notify_one();
90 }
91}
92
93pub struct Executor {
94 inner: raw::Executor,
95 not_send: PhantomData<*mut ()>,
96 signaler: Signaler,
97}
98
99impl Executor {
100 pub fn new() -> Self {
101 unsafe {
102 CLOCK_ZERO.as_mut_ptr().write(StdInstant::now());
103 embassy::time::set_clock(&StdClock);
104 embassy::rand::set_rand(&StdRand);
105 }
106
107 Self {
108 inner: raw::Executor::new(Signaler::signal, ptr::null_mut()),
109 not_send: PhantomData,
110 signaler: Signaler::new(),
111 }
112 }
113
114 pub fn set_alarm(&mut self, alarm: &'static dyn Alarm) {
115 self.inner.set_alarm(alarm);
116 }
117
118 /// Runs the executor.
119 ///
120 /// This function never returns.
121 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
122 self.inner.set_signal_ctx(&self.signaler as *const _ as _);
123
124 init(unsafe { self.inner.spawner() });
125
126 loop {
127 unsafe { self.inner.run_queued() };
128 self.signaler.wait();
93 } 129 }
94 } 130 }
95} 131}