Function spawn
pub fn spawn(future: impl Future<Output = ()> + 'static) -> TaskHandleExpand description
Create a new async background task.
This function allows creating a new async task in which Godot signals can be awaited, like it is possible in GDScript. If a reference to
Self is not flexible enough regarding lifetimes, your function calling spawn() can capture the state in a Gd<Self> pointer instead. The
TaskHandle that is returned provides synchronous introspection into the current state of the task.
Signals can be converted to futures in the following ways:
| Signal type | Simple future | Fallible future (handles freed object) |
|---|---|---|
| Untyped | Signal::to_future() | Signal::to_fallible_future() |
| Typed | TypedSignal::to_future() | TypedSignal::to_fallible_future() |
§Panics
If called from any other thread than the main thread.
§Examples
An example using timers:
#[derive(GodotClass)]
#[class(init, base=Node)]
struct Game {
base: Base<Node>,
}
#[godot_api]
impl Game {
// Async sleep using Godot timers. Takes `Gd<Self>` by value, so no `&self`/`&mut self`
// reference is held while the task is suspended at the await point.
async fn sleep(this: Gd<Self>, duration: f64) {
// To access object, use short-lived bind/bind_mut -> guard dropped after statement.
this.bind().do_something();
// Godot APIs don't need to go through bind/bind_mut at all.
let timer = this.get_tree().create_timer(duration);
// Await without holding any borrow on `this`. Keeping a bind()/bind_mut() guard
// across an await point is problematic: while suspended, other access to the
// object, for example through process(&mut self), will panic.
timer.signals().timeout().to_future().await;
}
fn show_messages(&mut self) {
// Obtain Gd<Self>, since the closure cannot capture `&mut self` due to lifetimes.
// If this method is linked to a signal, consider using a #[func(gd_self)] parameter.
let this = self.to_gd();
// spawn() polls the future up to the first .await point, during which `&mut self` is
// still held. base_mut() yields a guard that allows re-borrowing `self`, so the bind()
// inside sleep() doesn't panic with "already bound".
let _guard = self.base_mut();
godot::task::spawn(async move {
godot_print!("Start!");
Self::sleep(this, 1.0).await;
godot_print!("One second later!");
});
}
}With typed signals:
#[derive(GodotClass)]
#[class(init)]
struct Building {
base: Base<RefCounted>,
}
#[godot_api]
impl Building {
#[signal]
fn constructed(seconds: u32);
}
let house = Building::new_gd();
godot::task::spawn(async move {
println!("Wait for construction...");
// Emitted arguments can be fetched in tuple form.
// If the signal has no parameters, you can skip `let` and just await the future.
let (seconds,) = house.signals().constructed().to_future().await;
println!("Construction complete after {seconds}s.");
});With untyped signals:
let node = Node::new_alloc();
let signal = Signal::from_object_signal(&node, "signal");
godot::task::spawn(async move {
println!("Starting task...");
// Explicit generic arguments needed, here `()`:
signal.to_future::<()>().await;
println!("Node has changed: {}", node.get_name());
});