thread_executor/
lib.rs

1use std::future::Future;
2use std::task::{Context, Poll};
3
4use pin_utils::pin_mut;
5
6pub fn block_on<Fut: Future>(fut: Fut) -> Fut::Output {
7    let waker = waker::new(std::thread::current());
8    let mut context = Context::from_waker(&waker);
9
10    pin_mut!(fut);
11
12    loop {
13        if let Poll::Ready(out) = fut.as_mut().poll(&mut context) {
14            return out;
15        }
16
17        std::thread::park();
18    }
19}
20
21mod waker {
22    use std::task::{RawWakerVTable, RawWaker, Waker};
23    use std::thread::Thread;
24    use super::thread::{self, ThreadRef};
25
26    static VTABLE: RawWakerVTable = RawWakerVTable::new(
27        clone,
28        wake,
29        wake_by_ref,
30        drop,
31    );
32
33    pub fn new(thread: Thread) -> Waker {
34        let thread = ThreadRef::new(thread);
35        unsafe { Waker::from_raw(new_raw(thread)) }
36    }
37
38    pub fn new_raw(thread: ThreadRef) -> RawWaker {
39        let ptr = unsafe { thread::into_ptr(thread) };
40        RawWaker::new(ptr, &VTABLE)
41    }
42
43    unsafe fn clone(ptr: *const ()) -> RawWaker {
44        let thread = thread::from_ptr_ref(&ptr);
45        let thread = thread.clone();
46        new_raw(thread)
47    }
48
49    unsafe fn wake(ptr: *const ()) {
50        thread::from_ptr(ptr).unpark();
51    }
52
53    unsafe fn wake_by_ref(ptr: *const ()) {
54        thread::from_ptr_ref(&ptr).unpark();
55    }
56
57    unsafe fn drop(ptr: *const ()) {
58        thread::from_ptr(ptr);
59    }
60}
61
62/// Functions for casting a [`std::thread::Thread`] to and from a raw pointer
63/// for use in [`waker_impl`]. This is just a set of wrappers around transmute
64/// for supported cast operations. The soundness of the transmutes is assured
65/// with static assertions.
66mod thread {
67    use std::sync::Arc;
68    use std::thread::Thread;
69
70    pub type ThreadRef = Arc<Thread>;
71
72    static_assertions::assert_eq_size!(ThreadRef, *const ());
73    static_assertions::assert_eq_align!(ThreadRef, *const ());
74
75    pub unsafe fn from_ptr(ptr: *const ()) -> ThreadRef {
76        std::mem::transmute(ptr)
77    }
78
79    pub unsafe fn from_ptr_ref(ptr: &*const ()) -> &ThreadRef {
80        std::mem::transmute(ptr)
81    }
82
83    pub unsafe fn into_ptr(thread: ThreadRef) -> *const () {
84        std::mem::transmute(thread)
85    }
86}