Reducing the chances for race conditions in join.
This commit is contained in:
parent
55c9842e7d
commit
5c6790519b
@ -115,7 +115,10 @@ static size_t const BUF_BYTES = 2048;
|
||||
private: \
|
||||
intptr_t ref_count; \
|
||||
public: \
|
||||
void ref() { sync::increment(ref_count); } \
|
||||
void ref() { \
|
||||
intptr_t old = sync::increment(ref_count); \
|
||||
assert(old > 0); \
|
||||
} \
|
||||
void deref() { if(0 == sync::decrement(ref_count)) { delete this; } }
|
||||
|
||||
template <typename T> struct rc_base {
|
||||
|
@ -160,7 +160,17 @@ rust_kernel::get_task_by_id(rust_task_id id) {
|
||||
rust_task *task = NULL;
|
||||
// get leaves task unchanged if not found.
|
||||
task_table.get(id, &task);
|
||||
if(task) task->ref();
|
||||
if(task) {
|
||||
if(task->get_ref_count() == 0) {
|
||||
// this means the destructor is running, since the destructor
|
||||
// grabs the kernel lock to unregister the task. Pretend this
|
||||
// doesn't actually exist.
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
task->ref();
|
||||
}
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
|
||||
rust_port_id register_port(rust_port *port);
|
||||
void release_port(rust_port_id id);
|
||||
rust_port *get_port_by_id(rust_port_id id);
|
||||
|
||||
// Use this function sparingly. Depending on the ref count is generally
|
||||
// not at all safe.
|
||||
intptr_t get_ref_count() const { return ref_count; }
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -27,4 +27,4 @@ fn main(args: vec[str]) {
|
||||
task::_spawn(bind f(n));
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user