@@ -79,7 +79,7 @@ pub struct Scheduler {
79
79
/// A fast XorShift rng for scheduler use
80
80
rng : XorShiftRng ,
81
81
/// An IdleWatcher
82
- idle_watcher : IdleWatcher ,
82
+ idle_watcher : Option < IdleWatcher > ,
83
83
/// A flag to indicate whether or not the idle callback is active.
84
84
idle_flag : bool
85
85
}
@@ -128,9 +128,6 @@ impl Scheduler {
128
128
friend : Option < SchedHandle > )
129
129
-> Scheduler {
130
130
131
- let mut event_loop = event_loop;
132
- let idle_watcher = IdleWatcher :: new ( event_loop. uvio . uv_loop ( ) ) ;
133
-
134
131
Scheduler {
135
132
sleeper_list : sleeper_list,
136
133
message_queue : MessageQueue :: new ( ) ,
@@ -146,8 +143,8 @@ impl Scheduler {
146
143
run_anything : run_anything,
147
144
friend_handle : friend,
148
145
rng : XorShiftRng :: new ( ) ,
149
- idle_watcher : idle_watcher ,
150
- idle_flag : true
146
+ idle_watcher : None ,
147
+ idle_flag : false
151
148
}
152
149
}
153
150
@@ -175,9 +172,7 @@ impl Scheduler {
175
172
// Before starting our first task, make sure the idle callback
176
173
// is active. As we do not start in the sleep state this is
177
174
// important.
178
- do this. idle_watcher . start |_idle_watcher, _status| {
179
- Scheduler :: run_sched_once ( ) ;
180
- }
175
+ this. activate_idle ( ) ;
181
176
182
177
// Now, as far as all the scheduler state is concerned, we are
183
178
// inside the "scheduler" context. So we can act like the
@@ -318,23 +313,43 @@ impl Scheduler {
318
313
Local :: put ( sched) ;
319
314
}
320
315
321
- fn activate_idle ( & mut self ) {
316
+ fn activate_idle ( & mut self ) {
317
+ rtdebug ! ( "activating idle" ) ;
322
318
if self . idle_flag {
319
+ rtassert ! ( self . idle_watcher. is_some( ) ) ;
323
320
rtdebug ! ( "idle flag already set, not reactivating idle watcher" ) ;
324
321
} else {
325
322
rtdebug ! ( "idle flag was false, reactivating idle watcher" ) ;
326
323
self . idle_flag = true ;
327
- self . idle_watcher . restart ( ) ;
324
+ if self . idle_watcher . is_none ( ) {
325
+ // There's no idle handle yet. Create one
326
+ let mut idle_watcher = IdleWatcher :: new ( self . event_loop . uvio . uv_loop ( ) ) ;
327
+ do idle_watcher. start |_idle_watcher, _status| {
328
+ Scheduler :: run_sched_once ( ) ;
329
+ }
330
+ self. idle_watcher = Some ( idle_watcher) ;
331
+ } else {
332
+ self . idle_watcher . get_mut_ref ( ) . restart ( ) ;
333
+ }
328
334
}
329
335
}
330
336
331
337
fn pause_idle ( & mut self ) {
332
- if !self . idle_flag {
333
- rtdebug ! ( "idle flag false, not stopping idle watcher" ) ;
338
+ rtassert ! ( self . idle_watcher. is_some( ) ) ;
339
+ rtassert ! ( self . idle_flag) ;
340
+
341
+ rtdebug ! ( "stopping idle watcher" ) ;
342
+
343
+ self . idle_flag = false ;
344
+ if !self . no_sleep {
345
+ self . idle_watcher . get_mut_ref ( ) . stop ( ) ;
334
346
} else {
335
- rtdebug ! ( "idle flag true, stopping idle watcher" ) ;
336
- self . idle_flag = false ;
337
- self . idle_watcher . stop ( ) ;
347
+ rtdebug ! ( "closing idle watcher" ) ;
348
+ // The scheduler is trying to exit. Destroy the idle watcher
349
+ // to drop the reference to the event loop.
350
+ let mut idle_watcher = self . idle_watcher . take_unwrap ( ) ;
351
+ idle_watcher. stop ( ) ;
352
+ idle_watcher. close ( ||( ) ) ;
338
353
}
339
354
}
340
355
@@ -357,10 +372,15 @@ impl Scheduler {
357
372
358
373
let this = self ;
359
374
375
+ rtdebug ! ( "enqueuing task" ) ;
376
+
360
377
// We push the task onto our local queue clone.
361
378
this. work_queue . push ( task) ;
362
379
// this.event_loop.callback(Scheduler::run_sched_once);
363
380
381
+ // There is definitely work to be done later. Make sure we wake up for it.
382
+ this. activate_idle ( ) ;
383
+
364
384
// We've made work available. Notify a
365
385
// sleeping scheduler.
366
386
0 commit comments