toy_async_runtime/
runitime.rs

1//! Here we go, finally our runtime implementation,
2//! this will be a toy but with a very big ambition to begin a
3//! use runtime some day full od experimental idea that we want
4//! to test and see what is the impact of it.
5use 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
16/// Runtime definition
17pub(crate) struct Runtime {
18    task_queue: Queue,
19    spawner: Spawner,
20    /// Size of the runtime
21    pub(crate) size: AtomicUsize,
22}
23
24/// Runtime implementation, this is where the magic happens!
25impl Runtime {
26    /// start the runtime by spowing the event look on a thread!
27    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
58/// Configure the runtime!
59fn 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
71/// Spawn a non-blocking `Future` onto the `whorl` runtime
72pub fn spawn(future: impl Future<Output = ()> + Send + Sync + 'static) {
73    Runtime::spawner().spawn(future);
74}
75/// Block on a `Future` and stop others on the `whorl` runtime until this
76/// one completes.
77pub fn block_on(future: impl Future<Output = ()> + Send + Sync + 'static) {
78    Runtime::spawner().spawn_blocking(future);
79}
80/// Block further execution of a program until all of the tasks on the
81/// `whorl` runtime are completed.
82pub fn wait() {
83    let runtime = Runtime::get();
84    while runtime.size.load(Ordering::Relaxed) > 0 {}
85}