mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-11 06:24:24 +00:00
core: Remove private::chan_from_global_ptr. #3915
This commit is contained in:
parent
b9608fe423
commit
a3e087cefa
@ -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
|
||||
*
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user