toy_async_runtime/
runitime.rs1use std::collections::LinkedList;
6use std::future::Future;
7use std::sync::atomic::{AtomicUsize, Ordering};
8use std::sync::{Arc, Mutex};
9use std::task::Poll;
10
11use crate::spawner::Spawner;
12use crate::task::Task;
13
14pub(crate) type Queue = Arc<Mutex<LinkedList<Arc<Task>>>>;
15
16pub(crate) struct Runtime {
18 task_queue: Queue,
19 spawner: Spawner,
20 pub(crate) size: AtomicUsize,
22}
23
24impl Runtime {
26 fn start() {
28 std::thread::spawn(|| loop {
29 let task = match Runtime::get().pop_front() {
30 Some(task) => task,
31 None => continue,
32 };
33
34 if task.is_blocking() {
35 while let Poll::Pending = task.poll() {}
36 } else {
37 if let Poll::Pending = task.poll() {
38 task.waker();
39 }
40 }
41 });
42 }
43
44 pub fn get() -> &'static Runtime {
45 INSTANCE.get_or_init(configure)
46 }
47
48 pub fn spawner() -> Spawner {
49 Runtime::get().spawner.clone()
50 }
51
52 fn pop_front(&self) -> Option<Arc<Task>> {
53 self.task_queue.lock().unwrap().pop_front()
54 }
55}
56static INSTANCE: crate::lazy::Lazy<Runtime> = crate::lazy::Lazy::new();
57
58fn configure() -> Runtime {
60 Runtime::start();
61 let queue = Arc::new(Mutex::new(LinkedList::new()));
62 Runtime {
63 spawner: Spawner {
64 queue: queue.clone(),
65 },
66 task_queue: queue,
67 size: AtomicUsize::new(0),
68 }
69}
70
71pub fn spawn(future: impl Future<Output = ()> + Send + Sync + 'static) {
73 Runtime::spawner().spawn(future);
74}
75pub fn block_on(future: impl Future<Output = ()> + Send + Sync + 'static) {
78 Runtime::spawner().spawn_blocking(future);
79}
80pub fn wait() {
83 let runtime = Runtime::get();
84 while runtime.size.load(Ordering::Relaxed) > 0 {}
85}