Moved arc to libstd and added an arc that allows shared mutable state through mutual exclusion.
This commit is contained in:
parent
e394ebda37
commit
015527b0ce
8 changed files with 74 additions and 16 deletions
|
@ -2,9 +2,12 @@
|
|||
share immutable data between tasks."]
|
||||
|
||||
import comm::{port, chan, methods};
|
||||
import sys::methods;
|
||||
|
||||
export arc, get, clone, shared_arc, get_arc;
|
||||
|
||||
export exclusive, methods;
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
#[rust_stack]
|
||||
|
@ -16,12 +19,12 @@ native mod rustrt {
|
|||
-> libc::intptr_t;
|
||||
}
|
||||
|
||||
type arc_data<T: const> = {
|
||||
type arc_data<T> = {
|
||||
mut count: libc::intptr_t,
|
||||
data: T
|
||||
};
|
||||
|
||||
resource arc_destruct<T: const>(data: *libc::c_void) {
|
||||
resource arc_destruct<T>(data: *libc::c_void) {
|
||||
unsafe {
|
||||
let data: ~arc_data<T> = unsafe::reinterpret_cast(data);
|
||||
let new_count = rustrt::rust_atomic_decrement(&mut data.count);
|
||||
|
@ -71,6 +74,43 @@ fn clone<T: const>(rc: &arc<T>) -> arc<T> {
|
|||
arc_destruct(**rc)
|
||||
}
|
||||
|
||||
// An arc over mutable data that is protected by a lock.
|
||||
type ex_data<T> = {lock: sys::lock_and_signal, data: T};
|
||||
type exclusive<T> = arc_destruct<ex_data<T>>;
|
||||
|
||||
fn exclusive<T>(-data: T) -> exclusive<T> {
|
||||
let data = ~{mut count: 1, data: {lock: sys::create_lock(),
|
||||
data: data}};
|
||||
unsafe {
|
||||
let ptr = unsafe::reinterpret_cast(data);
|
||||
unsafe::forget(data);
|
||||
arc_destruct(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl methods<T> for exclusive<T> {
|
||||
fn clone() -> exclusive<T> {
|
||||
unsafe {
|
||||
// this makes me nervous...
|
||||
let ptr: ~arc_data<ex_data<T>> = unsafe::reinterpret_cast(*self);
|
||||
rustrt::rust_atomic_increment(&mut ptr.count);
|
||||
unsafe::forget(ptr);
|
||||
}
|
||||
arc_destruct(*self)
|
||||
}
|
||||
|
||||
fn with<U>(f: fn(sys::condition, x: &T) -> U) -> U {
|
||||
unsafe {
|
||||
let ptr: ~arc_data<ex_data<T>> = unsafe::reinterpret_cast(*self);
|
||||
let rec: &ex_data<T> = &(*ptr).data;
|
||||
unsafe::forget(ptr);
|
||||
rec.lock.lock_cond() {|c|
|
||||
f(c, &rec.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience code for sharing arcs between tasks
|
||||
|
||||
type get_chan<T: const send> = chan<chan<arc<T>>>;
|
||||
|
@ -115,6 +155,7 @@ fn get_arc<T: send const>(c: get_chan<T>) -> arc::arc<T> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
import comm::*;
|
||||
import future::future;
|
||||
|
||||
#[test]
|
||||
fn manually_share_arc() {
|
||||
|
@ -160,4 +201,31 @@ mod tests {
|
|||
|
||||
assert p.recv() == ();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exclusive_arc() {
|
||||
let mut futures = [];
|
||||
|
||||
let num_tasks = 10u;
|
||||
let count = 1000u;
|
||||
|
||||
let total = exclusive(~mut 0u);
|
||||
|
||||
for uint::range(0u, num_tasks) {|_i|
|
||||
let total = total.clone();
|
||||
futures += [future::spawn({||
|
||||
for uint::range(0u, count) {|_i|
|
||||
total.with {|_cond, count|
|
||||
**count += 1u;
|
||||
}
|
||||
}
|
||||
})];
|
||||
};
|
||||
|
||||
for futures.each {|f| f.get() };
|
||||
|
||||
total.with {|_cond, total|
|
||||
assert **total == num_tasks * count
|
||||
};
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ export float, f32, f64;
|
|||
export box, char, str, ptr, vec, bool;
|
||||
export either, option, result, iter;
|
||||
export libc, os, io, run, rand, sys, unsafe, logging;
|
||||
export comm, task, future;
|
||||
export arc, comm, task, future;
|
||||
export extfmt;
|
||||
export tuple;
|
||||
export to_str;
|
||||
|
@ -175,6 +175,7 @@ mod dvec_iter {
|
|||
}
|
||||
|
||||
// Concurrency
|
||||
mod arc;
|
||||
mod comm;
|
||||
mod task;
|
||||
mod future;
|
||||
|
|
|
@ -7,7 +7,7 @@ export min_align_of;
|
|||
export pref_align_of;
|
||||
export refcount;
|
||||
export log_str;
|
||||
export lock_and_signal, condition, methods;
|
||||
export create_lock, lock_and_signal, condition, methods;
|
||||
|
||||
enum type_desc = {
|
||||
first_param: **libc::c_int,
|
||||
|
@ -126,8 +126,6 @@ impl methods for condition {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std;
|
||||
import std::arc;
|
||||
|
||||
#[test]
|
||||
fn size_of_basic() {
|
||||
|
|
|
@ -19,7 +19,7 @@ export net, net_tcp;
|
|||
export uv, uv_ll, uv_iotask, uv_global_loop;
|
||||
export c_vec, util, timer;
|
||||
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap;
|
||||
export rope, arena, arc, par;
|
||||
export rope, arena, par;
|
||||
export ebml, dbg, getopts, json, rand, sha1, term, time, prettyprint;
|
||||
export test, tempfile, serialization;
|
||||
export cmp;
|
||||
|
@ -69,7 +69,6 @@ mod term;
|
|||
mod time;
|
||||
mod prettyprint;
|
||||
mod arena;
|
||||
mod arc;
|
||||
mod par;
|
||||
mod cmp;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import std::map;
|
|||
import std::map::hashmap;
|
||||
import std::deque;
|
||||
import std::deque::t;
|
||||
import std::arc;
|
||||
import std::par;
|
||||
import io::writer_util;
|
||||
import comm::*;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// error-pattern: copying a noncopyable value
|
||||
|
||||
use std;
|
||||
import std::arc;
|
||||
import comm::*;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std;
|
||||
import std::arc;
|
||||
import comm::*;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// error-pattern:explicit failure
|
||||
|
||||
use std;
|
||||
import std::arc;
|
||||
|
||||
enum e<T: const> { e(arc::arc<T>) }
|
||||
|
||||
fn foo() -> e<int> {fail;}
|
||||
|
|
Loading…
Add table
Reference in a new issue