Concurrency-enabled mechanisms for sharing mutable and/or immutable state between tasks.
In this example, a large vector of floats is shared between several tasks. With simple pipes, without ARC, a copy would have to be made for each task.
extern mod std;
use extra::arc;
let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random());
let shared_numbers=arc::ARC(numbers);
for 10.times {
let (port, chan) = stream();
chan.send(shared_numbers.clone());
do spawn {
let shared_numbers=port.recv();
let local_numbers=shared_numbers.get();
// Work with the local numbers
}
}
ARC
Condvar
- As sync::condvar, a mechanism for unlock-and-descheduling and signaling.RWReadMode
- The "read permission" token used for RWARCRWWriteMode
- The "write permission" token used for RWARCfor Condvar<'self> where <'self>
for ARC<T> where <T: Freeze + Send>
- Access the underlying data in an atomically reference counted wrapper.of Clone for ARC<T> where <T: Freeze + Send>
- Duplicate an atomically reference counted wrapper.of Clone for MutexARC<T> where <T: Send>
for MutexARC<T> where <T: Send>
of Drop for PoisonOnFail
for RWARC<T> where <T: Freeze + Send>
for RWARC<T> where <T: Freeze + Send>
for RWWriteMode<'self, T> where <'self, T: Freeze + Send>
for RWReadMode<'self, T> where <'self, T: Freeze + Send>
ARC
- Create an atomically reference counted wrapper.MutexARC
- Create a mutex-protected ARC with the supplied data.RWARC
- Create a reader/writer ARC with the supplied data.mutex_arc_with_condvars
- Create a mutex-protected ARC with the supplied data and a specified number of condvars (as sync::mutex_with_condvars).rw_arc_with_condvars
- Create a reader/writer ARC with the supplied data and a specified number of condvars (as sync::rwlock_with_condvars).ARC
pub struct ARC<T> {
x: UnsafeAtomicRcBox<T>,
}
Condvar
pub struct Condvar<'self> {
is_mutex: bool,
failed: &'self mut bool,
cond: &'self sync::Condvar<'self>,
}
As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
RWReadMode
pub struct RWReadMode<'self, T> {
data: &'self T,
token: sync::RWlockReadMode<'self>,
}
The "read permission" token used for RWARC.write_downgrade().
RWWriteMode
pub struct RWWriteMode<'self, T> {
data: &'self mut T,
token: sync::RWlockWriteMode<'self>,
poison: PoisonOnFail,
}
The "write permission" token used for RWARC.write_downgrade().
Condvar<'self>
where <'self>
wait
fn wait(&self)
Atomically exit the associated ARC and block until a signal is sent.
wait_on
fn wait_on(&self, condvar_id: uint)
Atomically exit the associated ARC and block on a specified condvar until a signal is sent on that same condvar (as sync::cond.wait_on).
wait() is equivalent to wait_on(0).
signal
fn signal(&self) -> bool
Wake up a blocked task. Returns false if there was no blocked task.
signal_on
fn signal_on(&self, condvar_id: uint) -> bool
Wake up a blocked task on a specified condvar (as sync::cond.signal_on). Returns false if there was no blocked task.
broadcast
fn broadcast(&self) -> uint
Wake up all blocked tasks. Returns the number of tasks woken.
broadcast_on
fn broadcast_on(&self, condvar_id: uint) -> uint
Wake up all blocked tasks on a specified condvar (as sync::cond.broadcast_on). Returns the number of tasks woken.
ARC<T>
where <T: Freeze + Send>
Access the underlying data in an atomically reference counted wrapper.
get
fn get<'a>(&'a self) -> &'a T
Clone
for ARC<T>
where <T: Freeze + Send>
Duplicate an atomically reference counted wrapper.
The resulting two arc
objects will point to the same underlying data object. However, one of the arc
objects can be sent to another task, allowing them to share the underlying data.
clone
fn clone(&self) -> ARC<T>
Clone
for MutexARC<T>
where <T: Send>
clone
fn clone(&self) -> MutexARC<T>
Duplicate a mutex-protected ARC, as arc::clone.
MutexARC<T>
where <T: Send>
access
unsafe fn access<U>(&self, blk: &fn(x: &mut T) -> U) -> U
Access the underlying mutable data with mutual exclusion from other tasks. The argument closure will be run with the mutex locked; all other tasks wishing to access the data will block until the closure finishes running.
The reason this function is 'unsafe' is because it is possible to construct a circular reference among multiple ARCs by mutating the underlying data. This creates potential for deadlock, but worse, this will guarantee a memory leak of all involved ARCs. Using mutex ARCs inside of other ARCs is safe in absence of circular references.
If you wish to nest mutex_arcs, one strategy for ensuring safety at runtime is to add a "nesting level counter" inside the stored data, and when traversing the arcs, assert that they monotonically decrease.
Failing while inside the ARC will unlock the ARC while unwinding, so that other tasks won't block forever. It will also poison the ARC: any tasks that subsequently try to access it (including those already blocked on the mutex) will also fail immediately.
access_cond
unsafe fn access_cond<'x, 'c,
U>(&self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U)
-> U
As access(), but with a condvar, as sync::mutex.lock_cond().
Drop
for PoisonOnFail
drop
fn drop(&self)
RWARC<T>
where <T: Freeze + Send>
clone
fn clone(&self) -> RWARC<T>
Duplicate a rwlock-protected ARC, as arc::clone.
RWARC<T>
where <T: Freeze + Send>
write
fn write<U>(&self, blk: &fn(x: &mut T) -> U) -> U
Access the underlying data mutably. Locks the rwlock in write mode; other readers and writers will block.
Failing while inside the ARC will unlock the ARC while unwinding, so that other tasks won't block forever. As MutexARC.access, it will also poison the ARC, so subsequent readers and writers will both also fail.
write_cond
fn write_cond<'x, 'c, U>(&self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U)
-> U
As write(), but with a condvar, as sync::rwlock.write_cond().
read
fn read<U>(&self, blk: &fn(x: &T) -> U) -> U
Access the underlying data immutably. May run concurrently with other reading tasks.
Failing will unlock the ARC while unwinding. However, unlike all other access modes, this will not poison the ARC.
write_downgrade
fn write_downgrade<U>(&self, blk: &fn(v: RWWriteMode<T>) -> U) -> U
As write(), but with the ability to atomically 'downgrade' the lock. See sync::rwlock.write_downgrade(). The RWWriteMode token must be used to obtain the &mut T, and can be transformed into a RWReadMode token by calling downgrade(), after which a &T can be obtained instead.
do arc.write_downgrade |mut write_token| {
do write_token.write_cond |state, condvar| {
... exclusive access with mutable state ...
}
let read_token = arc.downgrade(write_token);
do read_token.read |state| {
... shared access with immutable state ...
}
}
downgrade
fn downgrade<'a>(&self, token: RWWriteMode<'a, T>) -> RWReadMode<'a, T>
To be called inside of the write_downgrade block.
RWWriteMode<'self, T>
where <'self, T: Freeze + Send>
write
fn write<U>(&mut self, blk: &fn(x: &mut T) -> U) -> U
Access the pre-downgrade RWARC in write mode.
write_cond
fn write_cond<'x, 'c,
U>(&mut self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U
Access the pre-downgrade RWARC in write mode with a condvar.
RWReadMode<'self, T>
where <'self, T: Freeze + Send>
read
fn read<U>(&self, blk: &fn(x: &T) -> U) -> U
Access the post-downgrade rwlock in read mode.
ARC
fn ARC<T: Freeze + Send>(data: T) -> ARC<T>
Create an atomically reference counted wrapper.
MutexARC
fn MutexARC<T: Send>(user_data: T) -> MutexARC<T>
Create a mutex-protected ARC with the supplied data.
RWARC
fn RWARC<T: Freeze + Send>(user_data: T) -> RWARC<T>
Create a reader/writer ARC with the supplied data.
mutex_arc_with_condvars
fn mutex_arc_with_condvars<T: Send>(user_data: T, num_condvars: uint) ->
MutexARC<T>
Create a mutex-protected ARC with the supplied data and a specified number of condvars (as sync::mutex_with_condvars).
rw_arc_with_condvars
fn rw_arc_with_condvars<T: Freeze + Send>(user_data: T, num_condvars: uint) ->
RWARC<T>
Create a reader/writer ARC with the supplied data and a specified number of condvars (as sync::rwlock_with_condvars).