Skip to content

Commit 226ee7d

Browse files
committed
libcore: Remove mutable fields from task::spawn
1 parent 4dc1c29 commit 226ee7d

File tree

2 files changed

+85
-46
lines changed

2 files changed

+85
-46
lines changed

src/libcore/task/spawn.rs

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272

7373
#[doc(hidden)]; // FIXME #3538
7474

75+
use cast::transmute;
7576
use cast;
7677
use cell::Cell;
7778
use container::Map;
@@ -117,10 +118,10 @@ pub fn taskset_each(tasks: &TaskSet, blk: &fn(v: *rust_task) -> bool) {
117118
struct TaskGroupData {
118119
// All tasks which might kill this group. When this is empty, the group
119120
// can be "GC"ed (i.e., its link in the ancestor list can be removed).
120-
mut members: TaskSet,
121+
members: TaskSet,
121122
// All tasks unidirectionally supervised by (directly or transitively)
122123
// tasks in this group.
123-
mut descendants: TaskSet,
124+
descendants: TaskSet,
124125
}
125126
type TaskGroupArc = unstable::Exclusive<Option<TaskGroupData>>;
126127

@@ -145,11 +146,11 @@ struct AncestorNode {
145146
// Hence we assert that this counter monotonically decreases as we
146147
// approach the tail of the list.
147148
// FIXME(#3068): Make the generation counter togglable with #[cfg(debug)].
148-
generation: uint,
149-
// Should really be an immutable non-option. This way appeases borrowck.
150-
mut parent_group: Option<TaskGroupArc>,
149+
generation: uint,
150+
// Should really be a non-option. This way appeases borrowck.
151+
parent_group: Option<TaskGroupArc>,
151152
// Recursive rest of the list.
152-
mut ancestors: AncestorList,
153+
ancestors: AncestorList,
153154
}
154155

155156
struct AncestorList(Option<unstable::Exclusive<AncestorNode>>);
@@ -301,22 +302,26 @@ fn each_ancestor(list: &mut AncestorList,
301302

302303
// One of these per task.
303304
struct TCB {
304-
me: *rust_task,
305+
me: *rust_task,
305306
// List of tasks with whose fates this one's is intertwined.
306-
tasks: TaskGroupArc, // 'none' means the group has failed.
307+
tasks: TaskGroupArc, // 'none' means the group has failed.
307308
// Lists of tasks who will kill us if they fail, but whom we won't kill.
308-
mut ancestors: AncestorList,
309-
is_main: bool,
310-
notifier: Option<AutoNotify>,
309+
ancestors: AncestorList,
310+
is_main: bool,
311+
notifier: Option<AutoNotify>,
311312
}
312313

313314
impl Drop for TCB {
314315
// Runs on task exit.
315316
fn finalize(&self) {
316317
unsafe {
318+
let this: &mut TCB = transmute(self);
319+
317320
// If we are failing, the whole taskgroup needs to die.
318321
if rt::rust_task_is_unwinding(self.me) {
319-
for self.notifier.each |x| { x.failed = true; }
322+
for this.notifier.each_mut |x| {
323+
x.failed = true;
324+
}
320325
// Take everybody down with us.
321326
do access_group(&self.tasks) |tg| {
322327
kill_taskgroup(tg, self.me, self.is_main);
@@ -331,16 +336,21 @@ impl Drop for TCB {
331336
// with our own taskgroup, so long as both happen before we die.
332337
// We remove ourself from every ancestor we can, so no cleanup; no
333338
// break.
334-
for each_ancestor(&mut self.ancestors, None) |ancestor_group| {
339+
for each_ancestor(&mut this.ancestors, None) |ancestor_group| {
335340
leave_taskgroup(ancestor_group, self.me, false);
336341
};
337342
}
338343
}
339344
}
340345

341-
fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList,
342-
is_main: bool, notifier: Option<AutoNotify>) -> TCB {
343-
for notifier.each |x| { x.failed = false; }
346+
fn TCB(me: *rust_task,
347+
tasks: TaskGroupArc,
348+
ancestors: AncestorList,
349+
is_main: bool,
350+
mut notifier: Option<AutoNotify>) -> TCB {
351+
for notifier.each_mut |x| {
352+
x.failed = false;
353+
}
344354

345355
TCB {
346356
me: me,
@@ -353,7 +363,7 @@ fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList,
353363

354364
struct AutoNotify {
355365
notify_chan: Chan<TaskResult>,
356-
mut failed: bool,
366+
failed: bool,
357367
}
358368

359369
impl Drop for AutoNotify {
@@ -375,9 +385,12 @@ fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
375385
let newstate = util::replace(&mut *state, None);
376386
// If 'None', the group was failing. Can't enlist.
377387
if newstate.is_some() {
378-
let group = newstate.unwrap();
379-
taskset_insert(if is_member { &mut group.members }
380-
else { &mut group.descendants }, me);
388+
let mut group = newstate.unwrap();
389+
taskset_insert(if is_member {
390+
&mut group.members
391+
} else {
392+
&mut group.descendants
393+
}, me);
381394
*state = Some(group);
382395
true
383396
} else {
@@ -391,9 +404,12 @@ fn leave_taskgroup(state: TaskGroupInner, me: *rust_task,
391404
let newstate = util::replace(&mut *state, None);
392405
// If 'None', already failing and we've already gotten a kill signal.
393406
if newstate.is_some() {
394-
let group = newstate.unwrap();
395-
taskset_remove(if is_member { &mut group.members }
396-
else { &mut group.descendants }, me);
407+
let mut group = newstate.unwrap();
408+
taskset_remove(if is_member {
409+
&mut group.members
410+
} else {
411+
&mut group.descendants
412+
}, me);
397413
*state = Some(group);
398414
}
399415
}
@@ -451,23 +467,30 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
451467
/*##################################################################*
452468
* Step 1. Get spawner's taskgroup info.
453469
*##################################################################*/
454-
let spawner_group = match local_get(OldHandle(spawner), taskgroup_key!()) {
455-
None => {
456-
// Main task, doing first spawn ever. Lazily initialise here.
457-
let mut members = new_taskset();
458-
taskset_insert(&mut members, spawner);
459-
let tasks = unstable::exclusive(Some(TaskGroupData {
460-
members: members,
461-
descendants: new_taskset(),
462-
}));
463-
// Main task/group has no ancestors, no notifier, etc.
464-
let group =
465-
@TCB(spawner, tasks, AncestorList(None), true, None);
466-
local_set(OldHandle(spawner), taskgroup_key!(), group);
467-
group
468-
}
469-
Some(group) => group
470-
};
470+
let mut spawner_group: @@mut TCB =
471+
match local_get(OldHandle(spawner), taskgroup_key!()) {
472+
None => {
473+
// Main task, doing first spawn ever. Lazily initialise
474+
// here.
475+
let mut members = new_taskset();
476+
taskset_insert(&mut members, spawner);
477+
let tasks = unstable::exclusive(Some(TaskGroupData {
478+
members: members,
479+
descendants: new_taskset(),
480+
}));
481+
// Main task/group has no ancestors, no notifier, etc.
482+
let group = @@mut TCB(spawner,
483+
tasks,
484+
AncestorList(None),
485+
true,
486+
None);
487+
local_set(OldHandle(spawner), taskgroup_key!(), group);
488+
group
489+
}
490+
Some(group) => group
491+
};
492+
let spawner_group: &mut TCB = *spawner_group;
493+
471494
/*##################################################################*
472495
* Step 2. Process spawn options for child.
473496
*##################################################################*/
@@ -624,8 +647,11 @@ fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) {
624647
};
625648
626649
if enlist_many(child, &child_arc, &mut ancestors) {
627-
let group = @TCB(child, child_arc, ancestors,
628-
is_main, notifier);
650+
let group = @@mut TCB(child,
651+
child_arc,
652+
ancestors,
653+
is_main,
654+
notifier);
629655
unsafe {
630656
local_set(OldHandle(child), taskgroup_key!(), group);
631657
}

src/libcore/unstable.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,30 @@ pub impl LittleLock {
235235
}
236236
}
237237

238-
struct ExData<T> { lock: LittleLock, failed: bool, data: T, }
238+
struct ExData<T> {
239+
lock: LittleLock,
240+
failed: bool,
241+
data: T,
242+
}
243+
239244
/**
240245
* An arc over mutable data that is protected by a lock. For library use only.
241246
*/
242-
pub struct Exclusive<T> { x: SharedMutableState<ExData<T>> }
247+
pub struct Exclusive<T> {
248+
x: SharedMutableState<ExData<T>>
249+
}
243250

244251
pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
245252
let data = ExData {
246-
lock: LittleLock(), failed: false, data: user_data
253+
lock: LittleLock(),
254+
failed: false,
255+
data: user_data
247256
};
248-
Exclusive { x: unsafe { shared_mutable_state(data) } }
257+
Exclusive {
258+
x: unsafe {
259+
shared_mutable_state(data)
260+
}
261+
}
249262
}
250263

251264
impl<T:Owned> Clone for Exclusive<T> {

0 commit comments

Comments
 (0)