@@ -23,14 +23,13 @@ use super::message_queue::MessageQueue;
23
23
use rt:: kill:: BlockedTask ;
24
24
use rt:: local_ptr;
25
25
use rt:: local:: Local ;
26
- use rt:: rtio:: RemoteCallback ;
26
+ use rt:: rtio:: { RemoteCallback , PausibleIdleCallback } ;
27
27
use rt:: metrics:: SchedMetrics ;
28
28
use borrow:: { to_uint} ;
29
29
use cell:: Cell ;
30
30
use rand:: { XorShiftRng , RngUtil } ;
31
31
use iterator:: { range} ;
32
32
use vec:: { OwnedVector } ;
33
- use rt:: uv:: idle:: IdleWatcher ;
34
33
35
34
/// The Scheduler is responsible for coordinating execution of Coroutines
36
35
/// on a single thread. When the scheduler is running it is owned by
@@ -78,10 +77,13 @@ pub struct Scheduler {
78
77
friend_handle : Option < SchedHandle > ,
79
78
/// A fast XorShift rng for scheduler use
80
79
rng : XorShiftRng ,
81
- /// An IdleWatcher
82
- idle_watcher : Option < IdleWatcher > ,
83
- /// A flag to indicate whether or not the idle callback is active.
84
- idle_flag : bool
80
+ /// A toggleable idle callback
81
+ idle_callback : ~PausibleIdleCallback
82
+ }
83
+
84
+ enum CleanupJob {
85
+ DoNothing ,
86
+ GiveTask ( ~Task , UnsafeTaskReceiver )
85
87
}
86
88
87
89
pub struct SchedHandle {
@@ -97,11 +99,6 @@ pub enum SchedMessage {
97
99
TaskFromFriend ( ~Task )
98
100
}
99
101
100
- enum CleanupJob {
101
- DoNothing ,
102
- GiveTask ( ~Task , UnsafeTaskReceiver )
103
- }
104
-
105
102
impl Scheduler {
106
103
107
104
pub fn sched_id ( & self ) -> uint { to_uint ( self ) }
@@ -126,7 +123,10 @@ impl Scheduler {
126
123
sleeper_list : SleeperList ,
127
124
run_anything : bool ,
128
125
friend : Option < SchedHandle > )
129
- -> Scheduler {
126
+ -> Scheduler {
127
+
128
+ let mut event_loop = event_loop;
129
+ let idle_callback = event_loop. pausible_idle_callback ( ) ;
130
130
131
131
Scheduler {
132
132
sleeper_list : sleeper_list,
@@ -142,9 +142,8 @@ impl Scheduler {
142
142
metrics : SchedMetrics :: new ( ) ,
143
143
run_anything : run_anything,
144
144
friend_handle : friend,
145
- rng : XorShiftRng :: new ( ) ,
146
- idle_watcher : None ,
147
- idle_flag : false
145
+ rng : XorShiftRng :: new ( ) ,
146
+ idle_callback : idle_callback
148
147
}
149
148
}
150
149
@@ -172,7 +171,7 @@ impl Scheduler {
172
171
// Before starting our first task, make sure the idle callback
173
172
// is active. As we do not start in the sleep state this is
174
173
// important.
175
- this. activate_idle ( ) ;
174
+ this. idle_callback . start ( Scheduler :: run_sched_once ) ;
176
175
177
176
// Now, as far as all the scheduler state is concerned, we are
178
177
// inside the "scheduler" context. So we can act like the
@@ -194,14 +193,17 @@ impl Scheduler {
194
193
// cleaning up the memory it uses. As we didn't actually call
195
194
// task.run() on the scheduler task we never get through all
196
195
// the cleanup code it runs.
197
- let mut stask = Local :: take :: < Task > ( ) ;
196
+ let mut stask = Local :: take :: < Task > ( ) ;
198
197
199
198
rtdebug ! ( "stopping scheduler %u" , stask. sched. get_ref( ) . sched_id( ) ) ;
200
199
201
200
// Should not have any messages
202
201
let message = stask. sched . get_mut_ref ( ) . message_queue . pop ( ) ;
203
202
assert ! ( message. is_none( ) ) ;
204
203
204
+ // Close the idle callback.
205
+ stask. sched . get_mut_ref ( ) . idle_callback . close ( ) ;
206
+
205
207
stask. destroyed = true ;
206
208
}
207
209
@@ -211,11 +213,6 @@ impl Scheduler {
211
213
212
214
let mut self_sched = self ;
213
215
214
- // Always run through the scheduler loop at least once so that
215
- // we enter the sleep state and can then be woken up by other
216
- // schedulers.
217
- // self_sched.event_loop.callback(Scheduler::run_sched_once);
218
-
219
216
// This is unsafe because we need to place the scheduler, with
220
217
// the event_loop inside, inside our task. But we still need a
221
218
// mutable reference to the event_loop to give it the "run"
@@ -252,7 +249,7 @@ impl Scheduler {
252
249
253
250
// Assume that we need to continue idling unless we reach the
254
251
// end of this function without performing an action.
255
- sched. activate_idle ( ) ;
252
+ sched. idle_callback . resume ( ) ;
256
253
257
254
// Our first task is to read mail to see if we have important
258
255
// messages.
@@ -300,59 +297,19 @@ impl Scheduler {
300
297
let handle = sched. make_handle ( ) ;
301
298
sched. sleeper_list . push ( handle) ;
302
299
// Since we are sleeping, deactivate the idle callback.
303
- sched. pause_idle ( ) ;
300
+ sched. idle_callback . pause ( ) ;
304
301
} else {
305
302
rtdebug ! ( "not sleeping, already doing so or no_sleep set" ) ;
306
303
// We may not be sleeping, but we still need to deactivate
307
304
// the idle callback.
308
- sched. pause_idle ( ) ;
305
+ sched. idle_callback . pause ( ) ;
309
306
}
310
307
311
308
// Finished a cycle without using the Scheduler. Place it back
312
309
// in TLS.
313
310
Local :: put ( sched) ;
314
311
}
315
312
316
- fn activate_idle ( & mut self ) {
317
- rtdebug ! ( "activating idle" ) ;
318
- if self . idle_flag {
319
- rtassert ! ( self . idle_watcher. is_some( ) ) ;
320
- rtdebug ! ( "idle flag already set, not reactivating idle watcher" ) ;
321
- } else {
322
- rtdebug ! ( "idle flag was false, reactivating idle watcher" ) ;
323
- self . idle_flag = true ;
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
- }
334
- }
335
- }
336
-
337
- fn pause_idle ( & mut self ) {
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 ( ) ;
346
- } else {
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 ( ||( ) ) ;
353
- }
354
- }
355
-
356
313
pub fn make_handle ( & mut self ) -> SchedHandle {
357
314
let remote = self . event_loop . remote_callback ( Scheduler :: run_sched_once) ;
358
315
@@ -376,10 +333,9 @@ impl Scheduler {
376
333
377
334
// We push the task onto our local queue clone.
378
335
this. work_queue . push ( task) ;
379
- // this.event_loop.callback(Scheduler::run_sched_once);
380
336
381
337
// There is definitely work to be done later. Make sure we wake up for it.
382
- this. activate_idle ( ) ;
338
+ this. idle_callback . resume ( ) ;
383
339
384
340
// We've made work available. Notify a
385
341
// sleeping scheduler.
@@ -420,28 +376,23 @@ impl Scheduler {
420
376
let mut this = self ;
421
377
match this. message_queue . pop ( ) {
422
378
Some ( PinnedTask ( task) ) => {
423
- // this.event_loop.callback(Scheduler::run_sched_once);
424
379
let mut task = task;
425
380
task. give_home ( Sched ( this. make_handle ( ) ) ) ;
426
381
this. resume_task_immediately ( task) ;
427
382
return None ;
428
383
}
429
384
Some ( TaskFromFriend ( task) ) => {
430
- // this.event_loop.callback(Scheduler::run_sched_once);
431
385
rtdebug ! ( "got a task from a friend. lovely!" ) ;
432
386
this. sched_schedule_task ( task) . map_move ( Local :: put) ;
433
387
return None ;
434
388
}
435
389
Some ( Wake ) => {
436
- // this.event_loop.callback(Scheduler::run_sched_once);
437
390
this. sleepy = false ;
438
391
Local :: put ( this) ;
439
392
return None ;
440
- // return Some(this);
441
393
}
442
394
Some ( Shutdown ) => {
443
395
rtdebug ! ( "shutting down" ) ;
444
- // this.event_loop.callback(Scheduler::run_sched_once);
445
396
if this. sleepy {
446
397
// There may be an outstanding handle on the
447
398
// sleeper list. Pop them all to make sure that's
@@ -463,7 +414,6 @@ impl Scheduler {
463
414
464
415
Local :: put ( this) ;
465
416
return None ;
466
- // return Some(this);
467
417
}
468
418
None => {
469
419
return Some ( this) ;
0 commit comments