Skip to content

Commit

Permalink
add an example
Browse files Browse the repository at this point in the history
  • Loading branch information
hymm committed Jan 7, 2023
1 parent 12af897 commit adc3260
Showing 1 changed file with 45 additions and 8 deletions.
53 changes: 45 additions & 8 deletions crates/bevy_tasks/src/thread_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,45 @@ use std::{
use async_executor::{Executor, Task};
use futures_lite::Future;

/// An executor that can only be ticked on the thread it was instantiated on.
#[derive(Debug)]
/// An executor that can only be ticked on the thread it was instantiated on. But
/// can spawn `Send` tasks from other threads.
///
/// # Example
/// ```rust
/// # use std::sync::{Arc, atomic::{AtomicI32, Ordering}};
/// use bevy_tasks::ThreadExecutor;
///
/// let thread_executor = ThreadExecutor::new();
/// let count = Arc::new(AtomicI32::new(0));
///
/// // create some owned values that can be moved into another thread
/// let thread_executor_clone = thread_executor.clone();
/// let count_clone = count.clone();
/// let thread_spawner = thread_executor.spawner();
///
/// std::thread::scope(|scope| {
/// scope.spawn(|| {
/// // we cannot get the ticker from another thread
/// let not_thread_ticker = thread_executor_clone.ticker();
/// assert!(not_thread_ticker.is_none());
///
/// // but we can spawn tasks from another thread
/// thread_spawner.spawn(async move {
/// count_clone.fetch_add(1, Ordering::Relaxed);
/// }).detach();
/// });
/// });
///
/// // the tasks do not make progress unless the executor is manually ticked
/// assert_eq!(count.load(Ordering::Relaxed), 0);
///
/// // tick the ticker until task finishes
/// let thread_ticker = thread_executor.ticker().unwrap();
/// thread_ticker.try_tick();
/// assert_eq!(count.load(Ordering::Relaxed), 1);
/// ```
///
#[derive(Debug, Clone)]
pub struct ThreadExecutor {
executor: Arc<Executor<'static>>,
thread_id: ThreadId,
Expand All @@ -24,7 +61,7 @@ impl Default for ThreadExecutor {
}

impl ThreadExecutor {
/// createa a new `[ThreadExecutor]`
/// create a new `[ThreadExecutor]`
pub fn new() -> Self {
Self::default()
}
Expand Down Expand Up @@ -54,23 +91,23 @@ impl ThreadExecutor {
#[derive(Debug)]
pub struct ThreadSpawner<'a>(Arc<Executor<'a>>);
impl<'a> ThreadSpawner<'a> {
/// Spawn a task on the main thread
/// Spawn a task on the thread executor
pub fn spawn<T: Send + 'a>(&self, future: impl Future<Output = T> + Send + 'a) -> Task<T> {
self.0.spawn(future)
}
}

/// Used to tick the [`ThreadExecutor`]
/// Used to tick the [`ThreadExecutor`]. The executor does not
/// make progress unless it is manually ticked on the thread it was
/// created on.
#[derive(Debug)]
pub struct ThreadTicker {
executor: Arc<Executor<'static>>,
// make type not send or sync
_marker: PhantomData<*const ()>,
}
impl ThreadTicker {
/// Tick the main thread executor.
/// This needs to be called manually on the thread if it is not being used with
/// a `[TaskPool::scope]`.
/// Tick the thread executor.
pub fn tick(&self) -> impl Future<Output = ()> + '_ {
self.executor.tick()
}
Expand Down

0 comments on commit adc3260

Please sign in to comment.