@@ -7,8 +7,45 @@ use std::{
7
7
use async_executor:: { Executor , Task } ;
8
8
use futures_lite:: Future ;
9
9
10
- /// An executor that can only be ticked on the thread it was instantiated on.
11
- #[ derive( Debug ) ]
10
+ /// An executor that can only be ticked on the thread it was instantiated on. But
11
+ /// can spawn `Send` tasks from other threads.
12
+ ///
13
+ /// # Example
14
+ /// ```rust
15
+ /// # use std::sync::{Arc, atomic::{AtomicI32, Ordering}};
16
+ /// use bevy_tasks::ThreadExecutor;
17
+ ///
18
+ /// let thread_executor = ThreadExecutor::new();
19
+ /// let count = Arc::new(AtomicI32::new(0));
20
+ ///
21
+ /// // create some owned values that can be moved into another thread
22
+ /// let thread_executor_clone = thread_executor.clone();
23
+ /// let count_clone = count.clone();
24
+ /// let thread_spawner = thread_executor.spawner();
25
+ ///
26
+ /// std::thread::scope(|scope| {
27
+ /// scope.spawn(|| {
28
+ /// // we cannot get the ticker from another thread
29
+ /// let not_thread_ticker = thread_executor_clone.ticker();
30
+ /// assert!(not_thread_ticker.is_none());
31
+ ///
32
+ /// // but we can spawn tasks from another thread
33
+ /// thread_spawner.spawn(async move {
34
+ /// count_clone.fetch_add(1, Ordering::Relaxed);
35
+ /// }).detach();
36
+ /// });
37
+ /// });
38
+ ///
39
+ /// // the tasks do not make progress unless the executor is manually ticked
40
+ /// assert_eq!(count.load(Ordering::Relaxed), 0);
41
+ ///
42
+ /// // tick the ticker until task finishes
43
+ /// let thread_ticker = thread_executor.ticker().unwrap();
44
+ /// thread_ticker.try_tick();
45
+ /// assert_eq!(count.load(Ordering::Relaxed), 1);
46
+ /// ```
47
+ ///
48
+ #[ derive( Debug , Clone ) ]
12
49
pub struct ThreadExecutor {
13
50
executor : Arc < Executor < ' static > > ,
14
51
thread_id : ThreadId ,
@@ -24,7 +61,7 @@ impl Default for ThreadExecutor {
24
61
}
25
62
26
63
impl ThreadExecutor {
27
- /// createa a new `[ThreadExecutor]`
64
+ /// create a new `[ThreadExecutor]`
28
65
pub fn new ( ) -> Self {
29
66
Self :: default ( )
30
67
}
@@ -54,23 +91,23 @@ impl ThreadExecutor {
54
91
#[ derive( Debug ) ]
55
92
pub struct ThreadSpawner < ' a > ( Arc < Executor < ' a > > ) ;
56
93
impl < ' a > ThreadSpawner < ' a > {
57
- /// Spawn a task on the main thread
94
+ /// Spawn a task on the thread executor
58
95
pub fn spawn < T : Send + ' a > ( & self , future : impl Future < Output = T > + Send + ' a ) -> Task < T > {
59
96
self . 0 . spawn ( future)
60
97
}
61
98
}
62
99
63
- /// Used to tick the [`ThreadExecutor`]
100
+ /// Used to tick the [`ThreadExecutor`]. The executor does not
101
+ /// make progress unless it is manually ticked on the thread it was
102
+ /// created on.
64
103
#[ derive( Debug ) ]
65
104
pub struct ThreadTicker {
66
105
executor : Arc < Executor < ' static > > ,
67
106
// make type not send or sync
68
107
_marker : PhantomData < * const ( ) > ,
69
108
}
70
109
impl ThreadTicker {
71
- /// Tick the main thread executor.
72
- /// This needs to be called manually on the thread if it is not being used with
73
- /// a `[TaskPool::scope]`.
110
+ /// Tick the thread executor.
74
111
pub fn tick ( & self ) -> impl Future < Output = ( ) > + ' _ {
75
112
self . executor . tick ( )
76
113
}
0 commit comments