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
62mod 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}