core: Add priv::weaken_task
This commit is contained in:
@@ -37,8 +37,7 @@ enum rust_port {}
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
fn rust_port_id_send<T: send>(t: *sys::type_desc,
|
||||
target_port: port_id,
|
||||
fn rust_port_id_send<T: send>(target_port: port_id,
|
||||
data: T) -> libc::uintptr_t;
|
||||
|
||||
fn new_port(unit_sz: libc::size_t) -> *rust_port;
|
||||
@@ -114,7 +113,7 @@ whereupon the caller loses access to it.
|
||||
"]
|
||||
fn send<T: send>(ch: chan<T>, -data: T) {
|
||||
let chan_t(p) = ch;
|
||||
let res = rustrt::rust_port_id_send(sys::get_type_desc::<T>(), p, data);
|
||||
let res = rustrt::rust_port_id_send(p, data);
|
||||
if res != 0u unsafe {
|
||||
// Data sent successfully
|
||||
unsafe::forget(data);
|
||||
|
||||
@@ -4,10 +4,14 @@ export chan_from_global_ptr;
|
||||
|
||||
import compare_and_swap = rustrt::rust_compare_and_swap_ptr;
|
||||
|
||||
type rust_port_id = uint;
|
||||
|
||||
native mod rustrt {
|
||||
fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
|
||||
oldval: libc::uintptr_t,
|
||||
newval: libc::uintptr_t) -> bool;
|
||||
fn rust_task_weaken(ch: rust_port_id);
|
||||
fn rust_task_unweaken(ch: rust_port_id);
|
||||
}
|
||||
|
||||
type global_ptr<T: send> = *libc::uintptr_t;
|
||||
@@ -143,3 +147,83 @@ fn test_from_global_chan2() unsafe {
|
||||
assert winners == 1u;
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = "
|
||||
Convert the current task to a 'weak' task temporarily
|
||||
|
||||
As a weak task it will not be counted towards the runtime's set
|
||||
of live tasks. When there are no more outstanding live (non-weak) tasks
|
||||
the runtime will send an exit message on the provided channel.
|
||||
|
||||
This function is super-unsafe. Do not use.
|
||||
|
||||
# Safety notes
|
||||
|
||||
* Weak tasks must either die on their own or exit upon receipt of
|
||||
the exit message. Failure to do so will cause the runtime to never
|
||||
exit
|
||||
* Tasks must not call `weaken_task` multiple times. This will
|
||||
break the kernel's accounting of live tasks.
|
||||
* Weak tasks must not be supervised. A supervised task keeps
|
||||
a reference to its parent, so the parent will not die.
|
||||
"]
|
||||
unsafe fn weaken_task(f: fn(comm::port<()>)) unsafe {
|
||||
let po = comm::port();
|
||||
let ch = comm::chan(po);
|
||||
rustrt::rust_task_weaken(unsafe::reinterpret_cast(ch));
|
||||
let _unweaken = unweaken(ch);
|
||||
f(po);
|
||||
|
||||
resource unweaken(ch: comm::chan<()>) unsafe {
|
||||
rustrt::rust_task_unweaken(unsafe::reinterpret_cast(ch));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_then_unweaken() unsafe {
|
||||
task::try {||
|
||||
weaken_task {|_po|
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_wait() unsafe {
|
||||
let builder = task::builder();
|
||||
task::unsupervise(builder);
|
||||
task::run(builder) {||
|
||||
weaken_task {|po|
|
||||
comm::recv(po);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_stress() unsafe {
|
||||
// Create a bunch of weak tasks
|
||||
iter::repeat(100u) {||
|
||||
task::spawn {||
|
||||
weaken_task {|_po|
|
||||
}
|
||||
}
|
||||
let builder = task::builder();
|
||||
task::unsupervise(builder);
|
||||
task::run(builder) {||
|
||||
weaken_task {|po|
|
||||
// Wait for it to tell us to die
|
||||
comm::recv(po);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore(cfg(target_os = "win32"))]
|
||||
fn test_weaken_task_fail() unsafe {
|
||||
let res = task::try {||
|
||||
weaken_task {|_po|
|
||||
fail;
|
||||
}
|
||||
};
|
||||
assert result::is_failure(res);
|
||||
}
|
||||
Reference in New Issue
Block a user