1use std::future::Future;
2use std::marker::PhantomData;
3use std::mem;
4use std::pin::Pin;
5use std::process::abort;
6use std::sync::atomic::AtomicBool;
7use std::sync::atomic::Ordering;
8use std::sync::Arc;
9use std::task::Context;
10use std::task::Poll;
11use std::task::RawWaker;
12use std::task::RawWakerVTable;
13use std::task::Waker;
14use std::thread;
15use std::thread::Thread;
16
17pub fn abort_on_panic<R>(f: impl FnOnce() -> R) -> R {
21 struct Bomb;
22
23 impl Drop for Bomb {
24 fn drop(&mut self) {
25 abort();
26 }
27 }
28
29 let bomb = Bomb;
30
31 let r = f();
32
33 mem::forget(bomb);
34
35 r
36}
37
38#[derive(Debug)]
40pub struct Yields(pub usize);
41
42impl Future for Yields {
43 type Output = ();
44
45 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
46 if self.0 == 0 {
47 Poll::Ready(())
48 } else {
49 self.0 -= 1;
50 cx.waker().wake_by_ref();
51 Poll::Pending
52 }
53 }
54}
55
56pub fn block_on<F: Future>(f: F) -> F::Output {
58 static VTABLE: RawWakerVTable = RawWakerVTable::new(
59 |clone_me| {
60 let clone_me = unsafe { Arc::from_raw(clone_me as *const Unparker) };
61 mem::forget(clone_me.clone());
62 RawWaker::new(Arc::into_raw(clone_me) as *const (), &VTABLE)
63 },
64 |wake_me| unsafe { Arc::from_raw(wake_me as *const Unparker) }.unpark(),
65 |wake_me_by_ref| unsafe { &*(wake_me_by_ref as *const Unparker) }.unpark(),
66 |drop_me| drop(unsafe { Arc::from_raw(drop_me as *const Unparker) }),
67 );
68
69 let parker = Parker::new();
70
71 let waker = {
72 let raw = RawWaker::new(Arc::into_raw(parker.unparker()) as *const (), &VTABLE);
73 unsafe { Waker::from_raw(raw) }
74 };
75
76 let mut f = f;
77 let mut cx = Context::from_waker(&waker);
78 loop {
79 match unsafe { Pin::new_unchecked(&mut f) }.poll(&mut cx) {
80 Poll::Pending => parker.park(),
81 Poll::Ready(val) => return val,
82 }
83 }
84}
85
86struct ParkerInner {
87 parked: AtomicBool,
88 thread: Thread,
89
90 _marker: PhantomData<*mut ()>,
92}
93
94impl ParkerInner {
95 fn new() -> ParkerInner {
96 ParkerInner {
97 parked: AtomicBool::new(false),
98 thread: thread::current(),
99 _marker: PhantomData,
100 }
101 }
102
103 fn park(&self) {
104 while !self.parked.load(Ordering::Relaxed) {
106 thread::park();
107 }
108
109 self.parked.store(false, Ordering::Relaxed);
111 }
112
113 fn unpark(&self) {
114 self.parked.store(true, Ordering::Relaxed);
116
117 self.thread.unpark();
118 }
119}
120
121pub struct Parker(Arc<ParkerInner>);
123
124impl Parker {
125 pub fn new() -> Parker {
127 Parker(Arc::new(ParkerInner::new()))
128 }
129
130 pub fn park(&self) {
132 self.0.park();
133 }
134
135 pub fn unparker(&self) -> Arc<Unparker> {
137 let cloned = self.0.clone();
138 unsafe { mem::transmute(cloned) }
139 }
140}
141
142pub struct Unparker(ParkerInner);
144
145impl Unparker {
146 pub fn unpark(&self) {
148 self.0.unpark();
149 }
150}
151
152unsafe impl Send for Unparker {}
153unsafe impl Sync for Unparker {}