core: Remove private::chan_from_global_ptr. #3915
This commit is contained in:
parent
b9608fe423
commit
a3e087cefa
2 changed files with 2 additions and 154 deletions
|
@ -95,163 +95,11 @@ fn test_run_in_bare_thread() unsafe {
|
||||||
#[allow(non_camel_case_types)] // runtime type
|
#[allow(non_camel_case_types)] // runtime type
|
||||||
type rust_port_id = uint;
|
type rust_port_id = uint;
|
||||||
|
|
||||||
type GlobalPtr = *libc::uintptr_t;
|
|
||||||
|
|
||||||
fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
|
fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
|
||||||
let old = rusti::atomic_cxchg(address, oldval, newval);
|
let old = rusti::atomic_cxchg(address, oldval, newval);
|
||||||
old == oldval
|
old == oldval
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Atomically gets a channel from a pointer to a pointer-sized memory location
|
|
||||||
* or, if no channel exists creates and installs a new channel and sets up a
|
|
||||||
* new task to receive from it.
|
|
||||||
*/
|
|
||||||
pub unsafe fn chan_from_global_ptr<T: Owned>(
|
|
||||||
global: GlobalPtr,
|
|
||||||
task_fn: fn() -> task::TaskBuilder,
|
|
||||||
f: fn~(oldcomm::Port<T>)
|
|
||||||
) -> oldcomm::Chan<T> {
|
|
||||||
|
|
||||||
enum Msg {
|
|
||||||
Proceed,
|
|
||||||
Abort
|
|
||||||
}
|
|
||||||
|
|
||||||
log(debug,~"ENTERING chan_from_global_ptr, before is_prob_zero check");
|
|
||||||
let is_probably_zero = *global == 0u;
|
|
||||||
log(debug,~"after is_prob_zero check");
|
|
||||||
if is_probably_zero {
|
|
||||||
log(debug,~"is probably zero...");
|
|
||||||
// There's no global channel. We must make it
|
|
||||||
|
|
||||||
let (setup1_po, setup1_ch) = pipes::stream();
|
|
||||||
let (setup2_po, setup2_ch) = pipes::stream();
|
|
||||||
|
|
||||||
// FIXME #4422: Ugly type inference hint
|
|
||||||
let setup2_po: pipes::Port<Msg> = setup2_po;
|
|
||||||
|
|
||||||
do task_fn().spawn |move f, move setup1_ch, move setup2_po| {
|
|
||||||
let po = oldcomm::Port::<T>();
|
|
||||||
let ch = oldcomm::Chan(&po);
|
|
||||||
setup1_ch.send(ch);
|
|
||||||
|
|
||||||
// Wait to hear if we are the official instance of
|
|
||||||
// this global task
|
|
||||||
match setup2_po.recv() {
|
|
||||||
Proceed => f(move po),
|
|
||||||
Abort => ()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
log(debug,~"before setup recv..");
|
|
||||||
// This is the proposed global channel
|
|
||||||
let ch = setup1_po.recv();
|
|
||||||
// 0 is our sentinal value. It is not a valid channel
|
|
||||||
assert *ch != 0;
|
|
||||||
|
|
||||||
// Install the channel
|
|
||||||
log(debug,~"BEFORE COMPARE AND SWAP");
|
|
||||||
let swapped = compare_and_swap(
|
|
||||||
cast::reinterpret_cast(&global),
|
|
||||||
0, cast::reinterpret_cast(&ch));
|
|
||||||
log(debug,fmt!("AFTER .. swapped? %?", swapped));
|
|
||||||
|
|
||||||
if swapped {
|
|
||||||
// Success!
|
|
||||||
setup2_ch.send(Proceed);
|
|
||||||
ch
|
|
||||||
} else {
|
|
||||||
// Somebody else got in before we did
|
|
||||||
setup2_ch.send(Abort);
|
|
||||||
cast::reinterpret_cast(&*global)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log(debug, ~"global != 0");
|
|
||||||
cast::reinterpret_cast(&*global)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn test_from_global_chan1() {
|
|
||||||
|
|
||||||
// This is unreadable, right?
|
|
||||||
|
|
||||||
// The global channel
|
|
||||||
let globchan = 0;
|
|
||||||
let globchanp = ptr::addr_of(&globchan);
|
|
||||||
|
|
||||||
// Create the global channel, attached to a new task
|
|
||||||
let ch = unsafe {
|
|
||||||
do chan_from_global_ptr(globchanp, task::task) |po| {
|
|
||||||
let ch = oldcomm::recv(po);
|
|
||||||
oldcomm::send(ch, true);
|
|
||||||
let ch = oldcomm::recv(po);
|
|
||||||
oldcomm::send(ch, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Talk to it
|
|
||||||
let po = oldcomm::Port();
|
|
||||||
oldcomm::send(ch, oldcomm::Chan(&po));
|
|
||||||
assert oldcomm::recv(po) == true;
|
|
||||||
|
|
||||||
// This one just reuses the previous channel
|
|
||||||
let ch = unsafe {
|
|
||||||
do chan_from_global_ptr(globchanp, task::task) |po| {
|
|
||||||
let ch = oldcomm::recv(po);
|
|
||||||
oldcomm::send(ch, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Talk to the original global task
|
|
||||||
let po = oldcomm::Port();
|
|
||||||
oldcomm::send(ch, oldcomm::Chan(&po));
|
|
||||||
assert oldcomm::recv(po) == true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn test_from_global_chan2() {
|
|
||||||
|
|
||||||
for iter::repeat(100) {
|
|
||||||
// The global channel
|
|
||||||
let globchan = 0;
|
|
||||||
let globchanp = ptr::addr_of(&globchan);
|
|
||||||
|
|
||||||
let resultpo = oldcomm::Port();
|
|
||||||
let resultch = oldcomm::Chan(&resultpo);
|
|
||||||
|
|
||||||
// Spawn a bunch of tasks that all want to compete to
|
|
||||||
// create the global channel
|
|
||||||
for uint::range(0, 10) |i| {
|
|
||||||
do task::spawn {
|
|
||||||
let ch = unsafe {
|
|
||||||
do chan_from_global_ptr(
|
|
||||||
globchanp, task::task) |po| {
|
|
||||||
|
|
||||||
for uint::range(0, 10) |_j| {
|
|
||||||
let ch = oldcomm::recv(po);
|
|
||||||
oldcomm::send(ch, {i});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let po = oldcomm::Port();
|
|
||||||
oldcomm::send(ch, oldcomm::Chan(&po));
|
|
||||||
// We are The winner if our version of the
|
|
||||||
// task was installed
|
|
||||||
let winner = oldcomm::recv(po);
|
|
||||||
oldcomm::send(resultch, winner == i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// There should be only one winner
|
|
||||||
let mut winners = 0u;
|
|
||||||
for uint::range(0u, 10u) |_i| {
|
|
||||||
let res = oldcomm::recv(resultpo);
|
|
||||||
if res { winners += 1u };
|
|
||||||
}
|
|
||||||
assert winners == 1u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the current task to a 'weak' task temporarily
|
* Convert the current task to a 'weak' task temporarily
|
||||||
*
|
*
|
||||||
|
|
|
@ -75,10 +75,10 @@ fn get_monitor_task_gl() -> IoTask unsafe {
|
||||||
debug!("global monitor task starting");
|
debug!("global monitor task starting");
|
||||||
// As a weak task the runtime will notify us when to exit
|
// As a weak task the runtime will notify us when to exit
|
||||||
do weaken_task |weak_exit_po| {
|
do weaken_task |weak_exit_po| {
|
||||||
debug!("global monitor task is now weak");
|
debug!("global monitor task is weak");
|
||||||
weak_exit_po.recv();
|
weak_exit_po.recv();
|
||||||
iotask::exit(&iotask);
|
iotask::exit(&iotask);
|
||||||
debug!("global monitor task is leaving weakend state");
|
debug!("global monitor task is unweak");
|
||||||
};
|
};
|
||||||
debug!("global monitor task exiting");
|
debug!("global monitor task exiting");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue