Next Generation WASM Microkernel Operating System
at main 141 lines 4.2 kB view raw
1// Copyright 2025. Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use alloc::boxed::Box; 9use core::any::type_name; 10use core::panic::Location; 11 12use crate::error::{Closed, SpawnError}; 13use crate::task::id::Id; 14use crate::task::join_handle::JoinHandle; 15use crate::task::{Task, TaskRef}; 16 17pub struct TaskBuilder<'a, S> { 18 location: Option<Location<'a>>, 19 name: Option<&'a str>, 20 kind: &'a str, 21 schedule: S, 22} 23 24impl<'a, S> TaskBuilder<'a, S> 25where 26 S: Fn(TaskRef) -> Result<(), Closed>, 27{ 28 pub fn new(schedule: S) -> Self { 29 Self { 30 location: None, 31 name: None, 32 kind: "task", 33 schedule, 34 } 35 } 36 37 /// Override the name of tasks spawned by this builder. 38 /// 39 /// By default, tasks are unnamed. 40 pub fn name(mut self, name: &'a str) -> Self { 41 self.name = Some(name); 42 self 43 } 44 45 /// Override the kind string of tasks spawned by this builder, this will only show up 46 /// in debug messages and spans. 47 /// 48 /// By default, tasks are of kind `"kind"`. 49 pub fn kind(mut self, kind: &'a str) -> Self { 50 self.kind = kind; 51 self 52 } 53 54 /// Override the source code location that will be associated with tasks spawned by this builder. 55 /// 56 /// By default, tasks will inherit the source code location of where they have been first spawned. 57 pub fn location(mut self, location: Location<'a>) -> Self { 58 self.location = Some(location); 59 self 60 } 61 62 #[inline] 63 #[track_caller] 64 fn build<F, M>(&self, future: F, metadata: M) -> Task<F, M> 65 where 66 F: Future + Send, 67 F::Output: Send, 68 M: Send, 69 { 70 let id = Id::next(); 71 72 let loc = self.location.as_ref().unwrap_or(Location::caller()); 73 let span = tracing::trace_span!( 74 "task", 75 task.tid = id.as_u64(), 76 task.name = ?self.name, 77 task.kind = self.kind, 78 task.output = %type_name::<F::Output>(), 79 loc.file = loc.file(), 80 loc.line = loc.line(), 81 loc.col = loc.column(), 82 ); 83 84 Task::new(future, id, span, metadata) 85 } 86 87 /// Attempt spawn this [`Future`] onto the executor. 88 /// 89 /// This method returns a [`TaskRef`] which can be used to spawn it onto an [`crate::executor::Executor`] 90 /// and a [`JoinHandle`] which can be used to await the futures output as well as control some aspects 91 /// of its runtime behaviour (such as cancelling it). 92 /// 93 /// # Errors 94 /// 95 /// Returns [`AllocError`] when allocation of the task fails. 96 #[inline] 97 #[track_caller] 98 pub fn try_spawn<F>(&self, future: F) -> Result<JoinHandle<F::Output, ()>, SpawnError> 99 where 100 F: Future + Send, 101 F::Output: Send, 102 { 103 let task = self.build(future, ()); 104 let task = Box::try_new(task)?; 105 let (task, join) = TaskRef::new_allocated(task); 106 107 (self.schedule)(task)?; 108 109 Ok(join) 110 } 111 112 /// Attempt spawn this [`Future`] with the provided metadata onto the executor. 113 /// 114 /// This method returns a [`TaskRef`] which can be used to spawn it onto an [`crate::executor::Executor`] 115 /// and a [`JoinHandle`] which can be used to await the futures output as well as control some aspects 116 /// of its runtime behaviour (such as cancelling it). 117 /// 118 /// # Errors 119 /// 120 /// Returns [`AllocError`] when allocation of the task fails. 121 #[inline] 122 #[track_caller] 123 pub fn try_spawn_with_metadata<F, M>( 124 &self, 125 future: F, 126 metadata: M, 127 ) -> Result<JoinHandle<F::Output, M>, SpawnError> 128 where 129 F: Future + Send, 130 F::Output: Send, 131 M: Send, 132 { 133 let task = self.build(future, metadata); 134 let task = Box::try_new(task)?; 135 let (task, join) = TaskRef::new_allocated(task); 136 137 (self.schedule)(task)?; 138 139 Ok(join) 140 } 141}