@@ -78,19 +78,23 @@ where
78
78
/// `delta` is used for timing based operations
79
79
/// - `TickedTimer` uses this delta value to tick till completion
80
80
///
81
- /// `maybe_limit ` is used to limit the number of woken tasks run per tick
81
+ /// `limit ` is used to limit the number of woken tasks run per tick
82
82
/// - None would imply that there is no limit (all woken tasks would run)
83
83
/// - Some(limit) would imply that [0..limit] woken tasks would run,
84
84
/// even if more tasks are woken.
85
85
///
86
86
/// Tick is !Sync i.e cannot be invoked from multiple threads
87
87
///
88
88
/// NOTE: Will not run tasks that are woken/scheduled immediately after `Runnable::run`
89
- pub fn tick ( & self , delta : f64 ) {
89
+ pub fn tick ( & self , delta : f64 , limit : Option < usize > ) {
90
90
let _r = self . tick_event . send ( delta) ;
91
91
92
- // Clamp woken tasks to limit
93
- let num_woken_tasks = self . num_woken_tasks . load ( Ordering :: Relaxed ) ;
92
+ let mut num_woken_tasks = self . num_woken_tasks . load ( Ordering :: Relaxed ) ;
93
+ if let Some ( limit) = limit {
94
+ // Woken tasks should not exceed the allowed limit
95
+ num_woken_tasks = num_woken_tasks. min ( limit) ;
96
+ }
97
+
94
98
self . channel
95
99
. 1
96
100
. try_iter ( )
@@ -153,6 +157,20 @@ mod tests {
153
157
154
158
const DELTA : f64 = 1000.0 / 60.0 ;
155
159
160
+ #[ test]
161
+ fn test_one_task ( ) {
162
+ const DELTA : f64 = 1.0 / 60.0 ;
163
+ const LIMIT : Option < usize > = None ;
164
+
165
+ let executor = TickedAsyncExecutor :: default ( ) ;
166
+
167
+ executor. spawn_local ( "MyIdentifier" , async move { } ) . detach ( ) ;
168
+
169
+ // Make sure to tick your executor to run the tasks
170
+ executor. tick ( DELTA , LIMIT ) ;
171
+ assert_eq ! ( executor. num_tasks( ) , 0 ) ;
172
+ }
173
+
156
174
#[ test]
157
175
fn test_multiple_tasks ( ) {
158
176
let executor = TickedAsyncExecutor :: default ( ) ;
@@ -168,10 +186,10 @@ mod tests {
168
186
} )
169
187
. detach ( ) ;
170
188
171
- executor. tick ( DELTA ) ;
189
+ executor. tick ( DELTA , None ) ;
172
190
assert_eq ! ( executor. num_tasks( ) , 2 ) ;
173
191
174
- executor. tick ( DELTA ) ;
192
+ executor. tick ( DELTA , None ) ;
175
193
assert_eq ! ( executor. num_tasks( ) , 0 ) ;
176
194
}
177
195
@@ -190,7 +208,7 @@ mod tests {
190
208
}
191
209
} ) ;
192
210
assert_eq ! ( executor. num_tasks( ) , 2 ) ;
193
- executor. tick ( DELTA ) ;
211
+ executor. tick ( DELTA , None ) ;
194
212
195
213
executor
196
214
. spawn_local ( "CancelTasks" , async move {
@@ -203,7 +221,7 @@ mod tests {
203
221
204
222
// Since we have cancelled the tasks above, the loops should eventually end
205
223
while executor. num_tasks ( ) != 0 {
206
- executor. tick ( DELTA ) ;
224
+ executor. tick ( DELTA , None ) ;
207
225
}
208
226
}
209
227
@@ -224,7 +242,7 @@ mod tests {
224
242
let mut instances = vec ! [ ] ;
225
243
while executor. num_tasks ( ) != 0 {
226
244
let current = Instant :: now ( ) ;
227
- executor. tick ( DELTA ) ;
245
+ executor. tick ( DELTA , None ) ;
228
246
instances. push ( current. elapsed ( ) ) ;
229
247
std:: thread:: sleep ( Duration :: from_millis ( 16 ) ) ;
230
248
}
@@ -276,8 +294,28 @@ mod tests {
276
294
} )
277
295
. detach ( ) ;
278
296
279
- executor. tick ( DELTA ) ;
297
+ executor. tick ( DELTA , None ) ;
280
298
assert_eq ! ( executor. num_tasks( ) , 4 ) ;
281
299
drop ( executor) ;
282
300
}
301
+
302
+ #[ test]
303
+ fn test_limit ( ) {
304
+ let executor = TickedAsyncExecutor :: default ( ) ;
305
+ for i in 0 ..10 {
306
+ executor
307
+ . spawn_local ( format ! ( "{i}" ) , async move {
308
+ println ! ( "Finish {i}" ) ;
309
+ } )
310
+ . detach ( ) ;
311
+ }
312
+
313
+ for i in 0 ..10 {
314
+ let woken_tasks = executor. num_woken_tasks . load ( Ordering :: Relaxed ) ;
315
+ assert_eq ! ( woken_tasks, 10 - i) ;
316
+ executor. tick ( 0.1 , Some ( 1 ) ) ;
317
+ }
318
+
319
+ assert_eq ! ( executor. num_tasks( ) , 0 ) ;
320
+ }
283
321
}
0 commit comments