1use std::sync::{Arc, mpsc};
8
9use fdf_core::dispatcher::CurrentDispatcher;
10use libasync_dispatcher::{AsAsyncDispatcherRef, OnDispatcher};
11
12use super::*;
13
14pub fn run_in_driver<T: Send + 'static>(name: &str, p: impl FnOnce() -> T + Send + 'static) -> T {
17 run_in_driver_raw(name, true, false, |tx| tx.send(p()).unwrap())
18}
19
20pub fn run_in_driver_etc<T: Send + 'static>(
23 name: &str,
24 allow_thread_blocking: bool,
25 unsynchronized: bool,
26 p: impl FnOnce() -> T + Send + 'static,
27) -> T {
28 run_in_driver_raw(name, allow_thread_blocking, unsynchronized, |tx| tx.send(p()).unwrap())
29}
30
31pub fn spawn_in_driver<T: Send + 'static>(
34 name: &str,
35 p: impl Future<Output = T> + Send + 'static,
36) -> T {
37 run_in_driver_raw(name, true, false, |tx| {
38 CurrentDispatcher.spawn(async move { tx.send(p.await).unwrap() });
39 })
40}
41
42pub fn spawn_in_driver_etc<T: Send + 'static>(
45 name: &str,
46 allow_thread_blocking: bool,
47 unsynchronized: bool,
48 p: impl Future<Output = T> + Send + 'static,
49) -> T {
50 run_in_driver_raw(name, allow_thread_blocking, unsynchronized, |tx| {
51 CurrentDispatcher.spawn(async move { tx.send(p.await).unwrap() });
52 })
53}
54
55fn run_in_driver_raw<T: Send + 'static>(
56 name: &str,
57 allow_thread_blocking: bool,
58 unsynchronized: bool,
59 p: impl FnOnce(mpsc::Sender<T>) + Send + 'static,
60) -> T {
61 let env = Arc::new(Environment::start(0).unwrap());
62 let env_clone = env.clone();
63
64 let (shutdown_tx, shutdown_rx) = mpsc::channel();
65 let driver_value: u32 = 0x1337;
66 let driver_value_ptr = &driver_value as *const u32;
67 let driver = env.new_driver(driver_value_ptr);
68 let dispatcher = DispatcherBuilder::new().name(name);
69 let dispatcher =
70 if allow_thread_blocking { dispatcher.allow_thread_blocking() } else { dispatcher };
71 let dispatcher = if unsynchronized { dispatcher.unsynchronized() } else { dispatcher };
72 let dispatcher = dispatcher.shutdown_observer(move |dispatcher| {
73 assert!(!env_clone.dispatcher_has_queued_tasks(dispatcher.as_dispatcher_ref()));
76 });
77 let dispatcher = driver.new_dispatcher(dispatcher).unwrap().release();
78
79 let (finished_tx, finished_rx) = mpsc::channel();
80 dispatcher
81 .post_task_sync(move |_| {
82 p(finished_tx);
83 })
84 .unwrap();
85 let res = finished_rx.recv().unwrap();
86
87 driver.shutdown(move |driver| {
88 assert!(unsafe { *driver.0 } == 0x1337);
90 shutdown_tx.send(()).unwrap();
91 });
92
93 shutdown_rx.recv().unwrap();
94
95 res
96}