Skip to content

Commit

Permalink
core: Remove private::chan_from_global_ptr. rust-lang#3915
Browse files Browse the repository at this point in the history
  • Loading branch information
brson committed Jan 22, 2013
1 parent df5338a commit cfdb48a
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 154 deletions.
152 changes: 0 additions & 152 deletions src/libcore/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/uv_global_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down

0 comments on commit cfdb48a

Please sign in to comment.