Singleton
The Singleton pattern is a design pattern that restricts the instantiation of a class to a single instance. This is useful for a system that requires a single, global point of access to a particular resource.
In the context of Turbo-Engine, the Singleton pattern can be used to intern a value into a Vc
. This ensures that for a single value, there is exactly one resolved Vc
. This allows Vcs
to be compared for equality and used as keys in hashmaps or hashsets.
Usage
To use the Singleton pattern in Turbo-Engine:
- Make the
.cell()
method private (Use#[turbo_tasks::value]
instead of#[turbo_tasks::value(shared)]
). - Only call the
.cell()
method in a Turbo-Engine function which acts as a constructor. - The constructor arguments act as a key for the constructor task which ensures that the same value is always celled in the same task.
- Keep in mind that only resolved
Vcs
are equal. UnresolvedVcs
might not be equal to each other.
Example
Here is an example of how to implement the Singleton pattern in Turbo-Engine:
#[turbo_tasks::value]
struct SingletonString {
value: String,
}
#[turbo_tasks::value_impl]
impl SingletonString {
#[turbo_tasks::function]
fn new(value: String) -> Vc<SingletonString> {
Self { value }.cell()
}
}
#[test]
fn test_singleton() {
let a1 = SingletonString::new("a".to_string()).resolve().await?;
let a2 = SingletonString::new("a".to_string()).resolve().await?;
let b = SingletonString::new("b".to_string()).resolve().await?;
assert_eq!(a1, a2); // Resolved Vcs are equal
assert_neq!(a1, b);
let set = HashSet::from([a1, a2, b]);
assert_eq!(set.len(), 2); // Only two different values
}
In this example, SingletonString
is a struct that contains a single String
value. The new
function acts as a constructor for SingletonString
, ensuring that the same string value is always celled in the same task.