1use core::marker::PhantomData;
2
3use super::id_and_context::{TaskContext, TaskId};
4use super::traits::Task;
5
6pub struct BaseTask<F, R> {
10 pub(super) func: F,
11 pub(super) context: TaskContext,
12 pub(super) _phantom: PhantomData<R>,
13}
14
15impl<F, R> BaseTask<F, R>
16where
17 F: FnOnce() -> R + Send + 'static,
18 R: Send + 'static,
19{
20 pub fn new(func: F, context: TaskContext) -> Self {
22 Self {
23 func,
24 context,
25 _phantom: PhantomData,
26 }
27 }
28}
29
30pub struct Closure<F, R> {
34 base: BaseTask<F, R>,
35}
36
37impl<F, R> Closure<F, R>
38where
39 F: FnOnce() -> R + Send + 'static,
40 R: Send + 'static,
41{
42 pub fn new(func: F, context: TaskContext) -> Self {
44 Self {
45 base: BaseTask::new(func, context),
46 }
47 }
48
49 pub fn then<G, S>(self, continuation: G) -> Chained<Self, G>
51 where
52 G: FnOnce(R) -> S + Send + 'static,
53 S: Send + 'static,
54 {
55 Chained::new(self, continuation)
56 }
57
58 pub fn map<G, S>(self, mapper: G) -> Mapped<Self, G>
60 where
61 G: FnOnce(R) -> S + Send + 'static,
62 S: Send + 'static,
63 {
64 Mapped::new(self, mapper)
65 }
66}
67
68impl<F, R> Task for Closure<F, R>
69where
70 F: FnOnce() -> R + Send + 'static,
71 R: Send + 'static,
72{
73 type Output = R;
74
75 fn execute(self) -> Self::Output {
76 (self.base.func)()
77 }
78
79 fn context(&self) -> &TaskContext {
80 &self.base.context
81 }
82}
83
84pub struct Chained<T, F> {
88 task: T,
89 continuation: F,
90 context: TaskContext,
91}
92
93impl<T, F> Chained<T, F> {
94 pub fn new(task: T, continuation: F) -> Self
96 where
97 T: Task,
98 {
99 let _context = task.context().clone();
100 Self {
101 task,
102 continuation,
103 context: _context,
104 }
105 }
106}
107
108impl<T, F, U> Task for Chained<T, F>
109where
110 T: Task,
111 F: FnOnce(T::Output) -> U + Send + 'static,
112 U: Send + 'static,
113{
114 type Output = U;
115
116 fn execute(self) -> Self::Output {
117 let result = self.task.execute();
118 (self.continuation)(result)
119 }
120
121 fn context(&self) -> &TaskContext {
122 &self.context
123 }
124
125 fn is_stealable(&self) -> bool {
126 self.task.is_stealable()
127 }
128
129 fn estimated_cost(&self) -> u32 {
130 self.task.estimated_cost() + 1
131 }
132}
133
134pub struct Mapped<T, F> {
138 task: T,
139 mapper: F,
140 context: TaskContext,
141}
142
143impl<T, F> Mapped<T, F> {
144 pub fn new(task: T, mapper: F) -> Self
146 where
147 T: Task,
148 {
149 let _context = task.context().clone();
150 Self {
151 task,
152 mapper,
153 context: _context,
154 }
155 }
156}
157
158impl<T, F, U> Task for Mapped<T, F>
159where
160 T: Task,
161 F: FnOnce(T::Output) -> U + Send + 'static,
162 U: Send + 'static,
163{
164 type Output = U;
165
166 fn execute(self) -> Self::Output {
167 let result = self.task.execute();
168 (self.mapper)(result)
169 }
170
171 fn context(&self) -> &TaskContext {
172 &self.context
173 }
174
175 fn is_stealable(&self) -> bool {
176 self.task.is_stealable()
177 }
178
179 fn estimated_cost(&self) -> u32 {
180 self.task.estimated_cost()
181 }
182}
183
184#[allow(clippy::module_name_repetitions)]
188pub struct TaskBuilder {
189 context: TaskContext,
190}
191
192impl TaskBuilder {
193 #[must_use]
198 pub fn new() -> Self {
199 Self {
201 context: TaskContext::new(TaskId::new(0)),
202 }
203 }
204
205 #[must_use]
213 pub fn priority(mut self, priority: crate::Priority) -> Self {
214 self.context.priority = priority;
215 self
216 }
217
218 #[must_use]
226 pub fn name(mut self, name: &'static str) -> Self {
227 self.context.name = Some(name);
228 self
229 }
230
231 #[must_use]
239 pub fn with_id(mut self, id: TaskId) -> Self {
240 self.context.id = id;
241 self
242 }
243
244 pub fn build<F, R>(self, func: F) -> Closure<F, R>
246 where
247 F: FnOnce() -> R + Send + 'static,
248 R: Send + 'static,
249 {
250 Closure::new(func, self.context)
251 }
252}
253
254impl Default for TaskBuilder {
255 fn default() -> Self {
256 Self::new()
257 }
258}
259
260pub struct Parameterized<F, P> {
267 function: Option<F>,
269 parameters: Option<P>,
271 context: TaskContext,
273}
274
275impl<F, P> Parameterized<F, P> {
276 pub fn new(func: F, params: P, context: TaskContext) -> Self {
278 Self {
279 function: Some(func),
280 parameters: Some(params),
281 context,
282 }
283 }
284}
285
286impl<F, P, R> Task for Parameterized<F, P>
287where
288 F: FnOnce(P) -> R + Send + 'static,
289 P: Send + 'static,
290 R: Send + 'static,
291{
292 type Output = R;
293
294 fn execute(mut self) -> Self::Output {
295 let func = self.function.take().expect("Task already executed");
296 let params = self.parameters.take().expect("Parameters already used");
297 func(params)
298 }
299
300 fn context(&self) -> &TaskContext {
301 &self.context
302 }
303}
304
305pub struct Group {
312 tasks: Vec<Box<dyn FnOnce() + Send + 'static>>,
314 context: TaskContext,
316}
317
318impl Group {
319 #[must_use]
327 pub fn new(id: TaskId) -> Self {
328 Self {
329 tasks: Vec::new(),
330 context: TaskContext::new(id),
331 }
332 }
333
334 pub fn add_task<F>(&mut self, task_fn: F)
336 where
337 F: FnOnce() + Send + 'static,
338 {
339 self.tasks.push(Box::new(move || {
340 task_fn();
341 }));
342 }
343
344 #[must_use]
349 pub fn len(&self) -> usize {
350 self.tasks.len()
351 }
352
353 #[must_use]
358 pub fn is_empty(&self) -> bool {
359 self.tasks.is_empty()
360 }
361}
362
363impl Task for Group {
364 type Output = ();
365
366 fn execute(self) -> Self::Output {
367 for task_fn in self.tasks {
369 task_fn();
370 }
371 }
372
373 fn context(&self) -> &TaskContext {
374 &self.context
375 }
376
377 #[allow(clippy::cast_possible_truncation)]
378 fn estimated_cost(&self) -> u32 {
379 self.tasks.len() as u32
380 }
381}
382
383pub struct Spawner<F> {
390 spawner: Option<F>,
392 context: TaskContext,
394}
395
396impl<F> Spawner<F> {
397 pub fn new(spawner: F, context: TaskContext) -> Self {
399 Self {
400 spawner: Some(spawner),
401 context,
402 }
403 }
404}
405
406impl<F> Task for Spawner<F>
407where
408 F: FnOnce() + Send + 'static,
409{
410 type Output = ();
411
412 fn execute(mut self) -> Self::Output {
413 if let Some(spawner) = self.spawner.take() {
414 spawner();
415 }
416 }
417
418 fn context(&self) -> &TaskContext {
419 &self.context
420 }
421}