Next Generation WASM Microkernel Operating System
at trap_handler 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 crate::error::Closed; 9use crate::error::SpawnError; 10use crate::task::id::Id; 11use crate::task::join_handle::JoinHandle; 12use crate::task::{Task, TaskRef}; 13use alloc::boxed::Box; 14use core::alloc::Allocator; 15use core::any::type_name; 16use core::panic::Location; 17 18pub struct TaskBuilder<'a, S> { 19 location: Option<Location<'a>>, 20 name: Option<&'a str>, 21 kind: &'a str, 22 schedule: S, 23} 24 25impl<'a, S> TaskBuilder<'a, S> 26where 27 S: Fn(TaskRef) -> Result<(), Closed>, 28{ 29 pub fn new(schedule: S) -> Self { 30 Self { 31 location: None, 32 name: None, 33 kind: "task", 34 schedule, 35 } 36 } 37 38 /// Override the name of tasks spawned by this builder. 39 /// 40 /// By default, tasks are unnamed. 41 pub fn name(mut self, name: &'a str) -> Self { 42 self.name = Some(name); 43 self 44 } 45 46 /// Override the kind string of tasks spawned by this builder, this will only show up 47 /// in debug messages and spans. 48 /// 49 /// By default, tasks are of kind `"kind"`. 50 pub fn kind(mut self, kind: &'a str) -> Self { 51 self.kind = kind; 52 self 53 } 54 55 /// Override the source code location that will be associated with tasks spawned by this builder. 56 /// 57 /// By default, tasks will inherit the source code location of where they have been first spawned. 58 pub fn location(mut self, location: Location<'a>) -> Self { 59 self.location = Some(location); 60 self 61 } 62 63 #[inline] 64 #[track_caller] 65 fn build<F>(&self, future: F) -> Task<F> 66 where 67 F: Future + Send, 68 F::Output: 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) 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`] onto the executor using a custom [`Allocator`]. 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_in<F, A>( 124 &self, 125 future: F, 126 alloc: A, 127 ) -> Result<JoinHandle<F::Output>, SpawnError> 128 where 129 F: Future + Send, 130 F::Output: Send, 131 A: Allocator, 132 { 133 let task = self.build(future); 134 let task = Box::try_new_in(task, alloc)?; 135 let (task, join) = TaskRef::new_allocated(task); 136 137 (self.schedule)(task)?; 138 139 Ok(join) 140 } 141}