Skip to content

Commit bd382ee

Browse files
brsontoddaaro
authored andcommitted
std::rt: Touch up idle logic
1 parent 066ca17 commit bd382ee

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

src/libstd/rt/sched.rs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub struct Scheduler {
7979
/// A fast XorShift rng for scheduler use
8080
rng: XorShiftRng,
8181
/// An IdleWatcher
82-
idle_watcher: IdleWatcher,
82+
idle_watcher: Option<IdleWatcher>,
8383
/// A flag to indicate whether or not the idle callback is active.
8484
idle_flag: bool
8585
}
@@ -128,9 +128,6 @@ impl Scheduler {
128128
friend: Option<SchedHandle>)
129129
-> Scheduler {
130130

131-
let mut event_loop = event_loop;
132-
let idle_watcher = IdleWatcher::new(event_loop.uvio.uv_loop());
133-
134131
Scheduler {
135132
sleeper_list: sleeper_list,
136133
message_queue: MessageQueue::new(),
@@ -146,8 +143,8 @@ impl Scheduler {
146143
run_anything: run_anything,
147144
friend_handle: friend,
148145
rng: XorShiftRng::new(),
149-
idle_watcher: idle_watcher,
150-
idle_flag: true
146+
idle_watcher: None,
147+
idle_flag: false
151148
}
152149
}
153150

@@ -175,9 +172,7 @@ impl Scheduler {
175172
// Before starting our first task, make sure the idle callback
176173
// is active. As we do not start in the sleep state this is
177174
// important.
178-
do this.idle_watcher.start |_idle_watcher, _status| {
179-
Scheduler::run_sched_once();
180-
}
175+
this.activate_idle();
181176

182177
// Now, as far as all the scheduler state is concerned, we are
183178
// inside the "scheduler" context. So we can act like the
@@ -318,23 +313,43 @@ impl Scheduler {
318313
Local::put(sched);
319314
}
320315

321-
fn activate_idle(&mut self) {
316+
fn activate_idle(&mut self) {
317+
rtdebug!("activating idle");
322318
if self.idle_flag {
319+
rtassert!(self.idle_watcher.is_some());
323320
rtdebug!("idle flag already set, not reactivating idle watcher");
324321
} else {
325322
rtdebug!("idle flag was false, reactivating idle watcher");
326323
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+
}
328334
}
329335
}
330336

331337
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();
334346
} 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(||());
338353
}
339354
}
340355

@@ -357,10 +372,15 @@ impl Scheduler {
357372

358373
let this = self;
359374

375+
rtdebug!("enqueuing task");
376+
360377
// We push the task onto our local queue clone.
361378
this.work_queue.push(task);
362379
// this.event_loop.callback(Scheduler::run_sched_once);
363380

381+
// There is definitely work to be done later. Make sure we wake up for it.
382+
this.activate_idle();
383+
364384
// We've made work available. Notify a
365385
// sleeping scheduler.
366386

0 commit comments

Comments
 (0)