core: Remove private::chan_from_global_ptr. #3915

This commit is contained in:
Brian Anderson 2013-01-21 19:16:01 -08:00
parent b9608fe423
commit a3e087cefa
2 changed files with 2 additions and 154 deletions

View File

@ -95,163 +95,11 @@ fn test_run_in_bare_thread() unsafe {
#[allow(non_camel_case_types)] // runtime type
type rust_port_id = uint;
type GlobalPtr = *libc::uintptr_t;
fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
let old = rusti::atomic_cxchg(address, oldval, newval);
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
*

View File

@ -75,10 +75,10 @@ fn get_monitor_task_gl() -> IoTask unsafe {
debug!("global monitor task starting");
// As a weak task the runtime will notify us when to exit
do weaken_task |weak_exit_po| {
debug!("global monitor task is now weak");
debug!("global monitor task is weak");
weak_exit_po.recv();
iotask::exit(&iotask);
debug!("global monitor task is leaving weakend state");
debug!("global monitor task is unweak");
};
debug!("global monitor task exiting");
}