turbo_tasks/task/
local_task.rs1use std::{fmt, sync::Arc};
2
3use anyhow::{Result, anyhow};
4
5use crate::{
6 MagicAny, OutputContent, RawVc, TaskExecutionReason, TaskPersistence, TraitMethod,
7 TurboTasksBackendApi, ValueTypeId,
8 backend::{Backend, TaskExecutionSpec, TypedCellContent},
9 event::Event,
10 macro_helpers::NativeFunction,
11 registry,
12};
13
14pub enum LocalTask {
16 Scheduled { done_event: Event },
17 Done { output: OutputContent },
18}
19
20pub fn get_local_task_execution_spec<'a>(
21 turbo_tasks: &'_ dyn TurboTasksBackendApi<impl Backend + 'static>,
22 ty: &'a LocalTaskSpec,
23 persistence: TaskPersistence,
26) -> TaskExecutionSpec<'a> {
27 match ty.task_type {
28 LocalTaskType::Native { native_fn } => {
29 let span = native_fn.span(TaskPersistence::Local, TaskExecutionReason::Local);
30 let entered = span.enter();
31 let future = native_fn.execute(ty.this, &*ty.arg);
32 drop(entered);
33 TaskExecutionSpec { future, span }
34 }
35 LocalTaskType::ResolveNative { native_fn } => {
36 let span = native_fn.resolve_span(TaskPersistence::Local);
37 let entered = span.enter();
38 let future = Box::pin(LocalTaskType::run_resolve_native(
39 native_fn,
40 ty.this,
41 &*ty.arg,
42 persistence,
43 turbo_tasks.pin(),
44 ));
45 drop(entered);
46 TaskExecutionSpec { future, span }
47 }
48 LocalTaskType::ResolveTrait { trait_method } => {
49 let span = trait_method.resolve_span();
50 let entered = span.enter();
51 let future = Box::pin(LocalTaskType::run_resolve_trait(
52 trait_method,
53 ty.this.unwrap(),
54 &*ty.arg,
55 persistence,
56 turbo_tasks.pin(),
57 ));
58 drop(entered);
59 TaskExecutionSpec { future, span }
60 }
61 }
62}
63
64pub struct LocalTaskSpec {
65 pub(crate) this: Option<RawVc>,
67 pub(crate) arg: Box<dyn MagicAny>,
69 pub(crate) task_type: LocalTaskType,
70}
71
72#[derive(Copy, Clone)]
73pub enum LocalTaskType {
74 Native { native_fn: &'static NativeFunction },
76
77 ResolveNative { native_fn: &'static NativeFunction },
80
81 ResolveTrait { trait_method: &'static TraitMethod },
85}
86
87impl fmt::Display for LocalTaskType {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 LocalTaskType::Native { native_fn } => f.write_str(native_fn.name),
91 LocalTaskType::ResolveNative { native_fn } => write!(f, "*{}", native_fn.name),
92 LocalTaskType::ResolveTrait { trait_method } => write!(
93 f,
94 "*{}::{}",
95 trait_method.trait_name, trait_method.method_name
96 ),
97 }
98 }
99}
100
101impl LocalTaskType {
102 async fn run_resolve_native<B: Backend + 'static>(
105 native_fn: &'static NativeFunction,
106 mut this: Option<RawVc>,
107 arg: &dyn MagicAny,
108 persistence: TaskPersistence,
109 turbo_tasks: Arc<dyn TurboTasksBackendApi<B>>,
110 ) -> Result<RawVc> {
111 if let Some(this) = this.as_mut() {
112 *this = this.resolve().await?;
113 }
114 let arg = native_fn.arg_meta.resolve(arg).await?;
115 Ok(turbo_tasks.native_call(native_fn, this, arg, persistence))
116 }
117 async fn run_resolve_trait<B: Backend + 'static>(
119 trait_method: &'static TraitMethod,
120 this: RawVc,
121 arg: &dyn MagicAny,
122 persistence: TaskPersistence,
123 turbo_tasks: Arc<dyn TurboTasksBackendApi<B>>,
124 ) -> Result<RawVc> {
125 let this = this.resolve().await?;
126 let TypedCellContent(this_ty, _) = this.into_read().await?;
127
128 let native_fn = Self::resolve_trait_method_from_value(trait_method, this_ty)?;
129 let arg = native_fn.arg_meta.filter_and_resolve(arg).await?;
130 Ok(turbo_tasks.native_call(native_fn, Some(this), arg, persistence))
131 }
132
133 fn resolve_trait_method_from_value(
134 trait_method: &'static TraitMethod,
135 value_type: ValueTypeId,
136 ) -> Result<&'static NativeFunction> {
137 match registry::get_value_type(value_type).get_trait_method(trait_method) {
138 Some(native_fn) => Ok(native_fn),
139 None => Err(anyhow!(
140 "{} doesn't implement the trait for {:?}, the compiler should have flagged this",
141 registry::get_value_type(value_type),
142 trait_method
143 )),
144 }
145 }
146}
147
148#[cfg(test)]
149pub(crate) mod tests {
150 use super::*;
151 use crate::{self as turbo_tasks, Vc};
152
153 #[turbo_tasks::function]
154 fn mock_func_task() -> Vc<()> {
155 Vc::cell(())
156 }
157
158 #[turbo_tasks::value_trait]
159 trait MockTrait {
160 #[turbo_tasks::function]
161 fn mock_method_task() -> Vc<()>;
162 }
163
164 #[test]
165 fn test_fmt() {
166 crate::register();
167 assert_eq!(
168 LocalTaskType::Native {
169 native_fn: &MOCK_FUNC_TASK_FUNCTION,
170 }
171 .to_string(),
172 "mock_func_task",
173 );
174 assert_eq!(
175 LocalTaskType::ResolveTrait {
176 trait_method: MOCKTRAIT_TRAIT_TYPE.get("mock_method_task"),
177 }
178 .to_string(),
179 "*MockTrait::mock_method_task",
180 );
181 }
182}