onion_vm/lambda/scheduler/
async_scheduler.rs1use arc_gc::gc::GC;
2use std::{collections::VecDeque, sync::Arc};
3
4use crate::{
5 lambda::runnable::{Runnable, RuntimeError, StepResult},
6 types::{
7 async_handle::OnionAsyncHandle,
8 object::{GCArcStorage, OnionObjectCell, OnionObjectExt},
9 },
10 unwrap_step_result,
11};
12
13const NUM_PRIORITY_LEVELS: usize = 3; #[inline(always)]
17fn generate_sched_step(n: usize) -> u64 {
18 (1u64 << (n + 1)) - 1
19}
20
21pub struct Task {
22 runnable: Box<dyn Runnable>,
23 task_handler: (Arc<OnionAsyncHandle>, GCArcStorage),
24 priority: usize, }
26
27impl Task {
28 pub fn new(
29 runnable: Box<dyn Runnable>,
30 task_handler: (Arc<OnionAsyncHandle>, GCArcStorage),
31 priority: usize,
32 ) -> Self {
33 Self {
34 runnable,
35 task_handler,
36 priority,
37 }
38 }
39
40 pub fn copy(&self) -> Task {
41 Task {
42 runnable: self.runnable.copy(),
43 task_handler: self.task_handler.clone(),
44 priority: self.priority,
45 }
46 }
47
48 pub fn format_context(&self) -> Result<serde_json::Value, RuntimeError> {
49 let mut context = self.runnable.format_context()?;
50 context["priority"] = serde_json::json!(self.priority);
51 Ok(context)
52 }
53}
54
55pub struct AsyncScheduler {
56 queue: VecDeque<Task>,
57 main_task_handler: (Arc<OnionAsyncHandle>, GCArcStorage), step: u64, }
60
61impl AsyncScheduler {
62 pub fn new(main_task: Task) -> Self {
63 let mut queue = VecDeque::new();
64 let main_task_handler = main_task.task_handler.clone();
65 queue.push_back(main_task);
66 AsyncScheduler {
67 queue,
68 main_task_handler,
69 step: 0,
70 }
71 }
72}
73
74impl Runnable for AsyncScheduler {
75 fn step(&mut self, gc: &mut GC<OnionObjectCell>) -> StepResult {
76 let len = self.queue.len();
78 if len == 0 {
79 return StepResult::Return(
81 unwrap_step_result!(self.main_task_handler.0.value_of()).into(),
82 );
83 }
84 let mut i = 0;
85 self.step += 1;
86 while i < len {
87 if let Some(mut task) = self.queue.pop_front() {
88 if self.step % generate_sched_step(task.priority) == 0 {
90 let step_result = task.runnable.step(gc);
91 match step_result {
92 StepResult::Continue => {
93 task.priority = 0; self.queue.push_back(task);
95 }
96 StepResult::Return(ref result) => {
97 unwrap_step_result!(task.task_handler.0.set_result(result.weak()));
98 }
99 StepResult::Error(RuntimeError::Pending) => {
100 task.priority = std::cmp::min(task.priority + 1, NUM_PRIORITY_LEVELS);
102 self.queue.push_back(task);
103 }
104 e @ StepResult::Error(_) => return e,
105 StepResult::NewRunnable(_) => {
106 return StepResult::Error(RuntimeError::DetailedError(
108 "AsyncScheduler does not support NewRunnable"
109 .to_string()
110 .into(),
111 ));
112 }
113 StepResult::ReplaceRunnable(_) => {
114 return StepResult::Error(RuntimeError::DetailedError(
116 "AsyncScheduler does not support ReplaceRunnable"
117 .to_string()
118 .into(),
119 ));
120 }
121 StepResult::SpawnRunnable(new_task) => {
122 self.queue.push_back(*new_task);
123 self.queue.push_back(task);
124 }
125 StepResult::SetSelfObject(_) => {
126 self.queue.push_back(task);
127 }
128 }
129 } else {
130 self.queue.push_back(task);
132 }
133 }
134 i += 1;
135 }
136 StepResult::Continue
137 }
138
139 fn receive(
140 &mut self,
141 _step_result: &StepResult,
142 _gc: &mut GC<OnionObjectCell>,
143 ) -> Result<(), RuntimeError> {
144 Err(RuntimeError::DetailedError(
145 "AsyncScheduler does not support receive".to_string().into(),
146 ))
147 }
148
149 fn copy(&self) -> Box<dyn Runnable> {
150 let new_queue = self.queue.iter().map(|r| r.copy()).collect();
151 Box::new(AsyncScheduler {
152 queue: new_queue,
153 main_task_handler: self.main_task_handler.clone(),
154 step: self.step,
155 })
156 }
157
158 fn format_context(&self) -> Result<serde_json::Value, RuntimeError> {
159 let mut tasks_json_array = serde_json::Value::Array(vec![]);
160 for task in &self.queue {
161 let frame_json = task.format_context()?;
162 tasks_json_array.as_array_mut().unwrap().push(frame_json);
163 }
164 Ok(serde_json::json!({
165 "type": "AsyncScheduler",
166 "tasks": tasks_json_array,
167 "step": self.step
168 }))
169 }
170}