pub struct TaskPoolHandler { /* private fields */ }
Expand description
Asynchronous task handler is used as an executor for async functions (tasks), that in addition to them has a closure, that will be called when a task is finished. The main use case for such tasks is to off-thread a heavy task to one of background threads (from a thread pool on PC, or a microtask on WebAssembly) and when it is done, incorporate its result in your game’s state. A task and its “on-complete” closure could be pretty much anything: procedural world generation + adding a generated scene to the engine, asset loading + its instantiation, etc. It should be noted that a task itself is executed asynchronously (in other thread), while a closure - synchronously, just at the beginning of the next game loop iteration. This means, that you should never put heavy tasks into the closure, otherwise it will result in quite notable stutters.
There are two main methods - TaskPoolHandler::spawn_plugin_task
and TaskPoolHandler::spawn_script_task
.
They are somewhat similar, but the main difference between them is that the first one operates
on per plugin basis and the latter operates on scene node basis. This means that in case of
TaskPoolHandler::spawn_plugin_task
, it will accept an async task and when it is finished, it
will give you a result of the task and access to the plugin from which it was called, so you can
do some actions with the result. TaskPoolHandler::spawn_script_task
does somewhat the same, but
on a scene node basis - when a task is done, the “on-complete” closure will be provided with a
wide context, allowing you to modify the caller’s node state. See the docs for the respective
methods for more info.
Implementations§
Source§impl TaskPoolHandler
impl TaskPoolHandler
Sourcepub fn spawn_plugin_task<F, T, P, C>(&mut self, future: F, on_complete: C)where
F: AsyncTask<T>,
T: AsyncTaskResult,
P: Plugin,
for<'a, 'b> C: Fn(T, &mut P, &mut PluginContext<'a, 'b>) + 'static,
pub fn spawn_plugin_task<F, T, P, C>(&mut self, future: F, on_complete: C)where
F: AsyncTask<T>,
T: AsyncTaskResult,
P: Plugin,
for<'a, 'b> C: Fn(T, &mut P, &mut PluginContext<'a, 'b>) + 'static,
Spawns a task represented by the future
, that does something and then adds the result to
a plugin it was called from using the on_complete
closure.
§Example
#[derive(Visit, Reflect, Debug)]
struct MyGame {
data: Option<Vec<u8>>,
}
impl MyGame {
pub fn new(context: PluginContext) -> Self {
context.task_pool.spawn_plugin_task(
// Emulate heavy task by reading a potentially large file. The game will be fully
// responsive while it runs.
async move {
let mut file = File::open("some/file.txt").unwrap();
let mut data = Vec::new();
file.read_to_end(&mut data).unwrap();
data
},
// This closure is called when the future above has finished, but not immediately - on
// the next update iteration.
|data, game: &mut MyGame, _context| {
// Store the data in the game instance.
game.data = Some(data);
},
);
// Immediately return the new game instance with empty data.
Self { data: None }
}
}
impl Plugin for MyGame {
fn update(&mut self, _context: &mut PluginContext) {
// Do something with the data.
if let Some(data) = self.data.take() {
println!("The data is: {:?}", data);
}
}
}
Sourcepub fn spawn_script_task<F, T, C, S>(
&mut self,
scene_handle: Handle<Scene>,
node_handle: Handle<Node>,
script_index: usize,
future: F,
on_complete: C,
)where
F: AsyncTask<T>,
T: AsyncTaskResult,
for<'a, 'b, 'c> C: Fn(T, &mut S, &mut ScriptContext<'a, 'b, 'c>) + 'static,
S: ScriptTrait,
pub fn spawn_script_task<F, T, C, S>(
&mut self,
scene_handle: Handle<Scene>,
node_handle: Handle<Node>,
script_index: usize,
future: F,
on_complete: C,
)where
F: AsyncTask<T>,
T: AsyncTaskResult,
for<'a, 'b, 'c> C: Fn(T, &mut S, &mut ScriptContext<'a, 'b, 'c>) + 'static,
S: ScriptTrait,
Spawns a task represented by the future
, that does something and then adds the result to
a scene node’s script using the on_complete
closure. This method could be used to off-thread some
heavy work from usual update routine (for example - pathfinding).
§Examples
#[derive(Reflect, Visit, Default, Debug, Clone)]
struct MyScript;
impl ScriptTrait for MyScript {
fn on_start(&mut self, ctx: &mut ScriptContext) {
ctx.task_pool.spawn_script_task(
ctx.scene_handle,
ctx.handle,
ctx.script_index,
// Request loading of some heavy asset. It does not actually does the loading in the
// same routine, since asset loading itself is asynchronous, but we can't block the
// current thread on all support platforms to wait until the loading is done. So we
// have to use this approach to load assets on demand. Since every asset implements
// Future trait, it can be used directly as a future. Alternatively, you can use async
// move { } block here.
ctx.resource_manager.request::<Model>("path/to/model.fbx"),
// This closure will executed only when the upper future is done and only on the next
// update iteration.
|result, script: &mut MyScript, ctx| {
if let Ok(model) = result {
model.instantiate(&mut ctx.scene);
}
},
);
}
}
Auto Trait Implementations§
impl Freeze for TaskPoolHandler
impl !RefUnwindSafe for TaskPoolHandler
impl !Send for TaskPoolHandler
impl !Sync for TaskPoolHandler
impl Unpin for TaskPoolHandler
impl !UnwindSafe for TaskPoolHandler
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Any
. Could be used to downcast a trait object
to a particular type.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Any
. Could be used to downcast a trait object
to a particular type.fn into_any(self: Box<T>) -> Box<dyn Any>
Source§impl<T> FieldValue for Twhere
T: 'static,
impl<T> FieldValue for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.