Calls
Introduction
In Turbo-Engine, calls to turbo task functions are central to the operation of the system. This section explains how calls work within the Turbo-Engine framework, including the concepts of unresolved and resolved Vc<T>.
Making Calls
#![allow(unused)] fn main() { let vc: Vc<T> = some_turbo_tasks_function(); }
When you invoke a Turbo-Tasks Function, it returns a Vc<T>, which is a pointer to the task's return value. Here's what happens during a call:
- Immediate Return: The call returns instantly, and the task is queued for computation.
- Unresolved Vc: The returned Vcis a so called "unresolved"Vc, meaning it points to a return value that may not yet be computed.
Resolved vs Unresolved Vcs
- Unresolved Vc: An "unresolved" Vcpoints to a return value of a Task
- Resolved Vc: A "resolved" Vcpoints to a cell computed by a Task.
Resolving Vcs
To compare Vc values or ensure they are ready for use, you can resolve them:
#![allow(unused)] fn main() { let resolved = vc.resolve().await?; }
- Reading: It's not mandatory to resolve Vcs before reading them. ReadingVcs will first resolve it and then read the cell value.
- Dependency Registration: Resolving a Vcregisters the current task as a dependent of the task output, ensuring that the task is recomputed if the return value changes.
- Usage as Key: Resolving Vcs is mandatory when using them as keys ofHashMaporHashSetfor the cell identity.
Importance of Resolution
Resolution is crucial for the memoization process:
- Memoization: Vcs used as arguments are identified by their pointer.
- Automatic Resolution: Unresolved Vcs passed to turbo task functions are resolved automatically, ensuring that functions receive resolvedVcs for memoization.- Intermediate Task: An intermediate task is created internally to handle the resolution of arguments.
 
Performance Considerations
While automatic resolution is convenient, it introduces the slight overhead of the intermediate Task:
- Manual Resolution: In performance-critical scenarios, resolving Vcs manually may be beneficial to reduce overhead.
Code Example
Here's an example of calling a turbo task function and resolving its Vc:
#![allow(unused)] fn main() { // Calling a turbo task function let vc: Vc<MyType> = compute_something(); // Resolving the Vc for direct comparison or use let resolved_vc: MyType = vc.resolve().await?; }