Adding shared_arc to hide some of the tedium of sharing an arc between tasks.
Also added some asserts and logging to trans. Modified graph500 to use the shared_arc, but this unfortunately doesn't work due to #2444.
This commit is contained in:
parent
3f0358bc5c
commit
aa2efc05ea
@ -1,7 +1,9 @@
|
||||
#[doc = "An atomically reference counted wrapper that can be used to
|
||||
share immutable data between tasks."]
|
||||
|
||||
export arc, get, clone;
|
||||
import comm::{port, chan, methods};
|
||||
|
||||
export arc, get, clone, shared_arc, get_arc;
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
@ -14,12 +16,12 @@ native mod rustrt {
|
||||
-> libc::intptr_t;
|
||||
}
|
||||
|
||||
type arc_data<T> = {
|
||||
type arc_data<T: const> = {
|
||||
mut count: libc::intptr_t,
|
||||
data: T
|
||||
};
|
||||
|
||||
resource arc_destruct<T>(data: *libc::c_void) {
|
||||
resource arc_destruct<T: const>(data: *libc::c_void) {
|
||||
unsafe {
|
||||
let data: ~arc_data<T> = unsafe::reinterpret_cast(data);
|
||||
let ref_ptr = &mut data.count;
|
||||
@ -34,10 +36,10 @@ resource arc_destruct<T>(data: *libc::c_void) {
|
||||
}
|
||||
}
|
||||
|
||||
type arc<T> = arc_destruct<T>;
|
||||
type arc<T: const> = arc_destruct<T>;
|
||||
|
||||
#[doc="Create an atomically reference counted wrapper."]
|
||||
fn arc<T>(-data: T) -> arc<T> {
|
||||
fn arc<T: const>(-data: T) -> arc<T> {
|
||||
let data = ~{mut count: 1, data: data};
|
||||
unsafe {
|
||||
let ptr = unsafe::reinterpret_cast(data);
|
||||
@ -48,7 +50,7 @@ fn arc<T>(-data: T) -> arc<T> {
|
||||
|
||||
#[doc="Access the underlying data in an atomically reference counted
|
||||
wrapper."]
|
||||
fn get<T>(rc: &a.arc<T>) -> &a.T {
|
||||
fn get<T: const>(rc: &a.arc<T>) -> &a.T {
|
||||
unsafe {
|
||||
let ptr: ~arc_data<T> = unsafe::reinterpret_cast(**rc);
|
||||
// Cast us back into the correct region
|
||||
@ -63,7 +65,7 @@ fn get<T>(rc: &a.arc<T>) -> &a.T {
|
||||
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."]
|
||||
fn clone<T>(rc: &arc<T>) -> arc<T> {
|
||||
fn clone<T: const>(rc: &arc<T>) -> arc<T> {
|
||||
unsafe {
|
||||
let ptr: ~arc_data<T> = unsafe::reinterpret_cast(**rc);
|
||||
rustrt::rust_atomic_increment(&mut ptr.count);
|
||||
@ -71,3 +73,36 @@ fn clone<T>(rc: &arc<T>) -> arc<T> {
|
||||
}
|
||||
arc_destruct(**rc)
|
||||
}
|
||||
|
||||
// Convenience code for sharing arcs between tasks
|
||||
|
||||
enum proto<T: send const> {
|
||||
terminate,
|
||||
shared_get(comm::chan<arc::arc<T>>)
|
||||
}
|
||||
|
||||
resource shared_arc_res<T: send const>(c: comm::chan<proto<T>>) {
|
||||
c.send(terminate);
|
||||
}
|
||||
|
||||
fn shared_arc<T: send const>(-data: T) -> shared_arc_res<T> {
|
||||
let a = arc::arc(data);
|
||||
let c = task::spawn_listener::<proto<T>>() {|p, move a|
|
||||
let mut live = true;
|
||||
while live {
|
||||
alt p.recv() {
|
||||
terminate { live = false; }
|
||||
shared_get(cc) {
|
||||
cc.send(arc::clone(&a));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
shared_arc_res(c)
|
||||
}
|
||||
|
||||
fn get_arc<T: send const>(c: comm::chan<proto<T>>) -> arc::arc<T> {
|
||||
let p = port();
|
||||
c.send(shared_get(chan(p)));
|
||||
p.recv()
|
||||
}
|
||||
|
@ -2028,6 +2028,14 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
||||
}
|
||||
});
|
||||
|
||||
#debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?",
|
||||
fn_id, ty::item_path_str(ccx.tcx, fn_id),
|
||||
real_substs.map({|s| ty_to_str(ccx.tcx, s)}),
|
||||
substs.map({|s| ty_to_str(ccx.tcx, s)})];
|
||||
|
||||
for real_substs.each() {|s| assert !ty::type_has_params(s); };
|
||||
for substs.each() {|s| assert !ty::type_has_params(s); };
|
||||
|
||||
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
|
||||
let hash_id = make_mono_id(ccx, fn_id, substs, vtables, some(param_uses));
|
||||
if vec::any(hash_id.params,
|
||||
@ -4231,6 +4239,7 @@ fn alloc_ty(bcx: block, t: ty::t) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("alloc_ty");
|
||||
let ccx = bcx.ccx();
|
||||
let llty = type_of(ccx, t);
|
||||
if ty::type_has_params(t) { log(error, ty_to_str(ccx.tcx, t)); }
|
||||
assert !ty::type_has_params(t);
|
||||
let val = alloca(bcx, llty);
|
||||
ret val;
|
||||
|
@ -14,6 +14,7 @@ import syntax::ast;
|
||||
import syntax::ast_util::{dummy_sp, new_def_hash};
|
||||
import syntax::util::interner;
|
||||
import util::common;
|
||||
import util::ppaux::ty_to_str;
|
||||
import syntax::codemap::span;
|
||||
import dvec::{dvec, extensions};
|
||||
|
||||
@ -445,6 +446,11 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
|
||||
s
|
||||
}
|
||||
ty::ty_res(did, raw_subt, substs) {
|
||||
#debug["ty_res(%?, %?, %?)",
|
||||
did,
|
||||
ty_to_str(ccx.tcx, raw_subt),
|
||||
substs.tps.map({|t| ty_to_str(ccx.tcx, t) })];
|
||||
for substs.tps.each() {|t| assert !ty::type_has_params(t); }
|
||||
let subt = ty::subst(ccx.tcx, substs, raw_subt);
|
||||
let tps = substs.tps;
|
||||
let ri = {did: did, tps: tps};
|
||||
@ -589,8 +595,9 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
|
||||
let mut dtors = [];
|
||||
let len = interner::len(ccx.shape_cx.resources);
|
||||
for uint::range(0u, len) {|i|
|
||||
let ri = interner::get(ccx.shape_cx.resources, i);
|
||||
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
|
||||
let ri = interner::get(ccx.shape_cx.resources, i);
|
||||
for ri.tps.each() {|s| assert !ty::type_has_params(s); }
|
||||
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
|
||||
}
|
||||
ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// xfail-test :(
|
||||
|
||||
/**
|
||||
|
||||
An implementation of the Graph500 Bread First Search problem in Rust.
|
||||
@ -10,6 +12,7 @@ import std::map;
|
||||
import std::map::hashmap;
|
||||
import std::deque;
|
||||
import std::deque::t;
|
||||
import std::arc;
|
||||
import io::writer_util;
|
||||
import comm::*;
|
||||
import int::abs;
|
||||
@ -264,34 +267,41 @@ fn pbfs(graph: graph, key: node_id) -> bfs_result {
|
||||
}
|
||||
}
|
||||
|
||||
let graph_arc = arc::shared_arc(copy graph);
|
||||
let graph = *graph_arc;
|
||||
|
||||
let mut i = 0u;
|
||||
while par::any(colors, is_gray) {
|
||||
// Do the BFS.
|
||||
log(info, #fmt("PBFS iteration %?", i));
|
||||
i += 1u;
|
||||
let old_len = colors.len();
|
||||
let pc = ptr::addr_of(colors);
|
||||
let pg = ptr::addr_of(graph);
|
||||
|
||||
let colors_arc = arc::shared_arc(copy colors);
|
||||
let color = *colors_arc;
|
||||
|
||||
colors = par::mapi(colors) {|i, c|
|
||||
let c : color = c;
|
||||
let colors = &arc::get_arc(color);
|
||||
let colors : [color] = *arc::get(colors);
|
||||
let graph = &arc::get_arc(graph);
|
||||
let graph : graph = *arc::get(graph);
|
||||
alt c {
|
||||
white {
|
||||
unsafe {
|
||||
let i = i as node_id;
|
||||
|
||||
let neighbors = &(*pg)[i];
|
||||
|
||||
let mut color = white;
|
||||
|
||||
(*neighbors).each() {|k|
|
||||
if is_gray((*pc)[k]) {
|
||||
color = gray(k);
|
||||
false
|
||||
}
|
||||
else { true }
|
||||
let i = i as node_id;
|
||||
|
||||
let neighbors = graph[i];
|
||||
|
||||
let mut color = white;
|
||||
|
||||
neighbors.each() {|k|
|
||||
if is_gray(colors[k]) {
|
||||
color = gray(k);
|
||||
false
|
||||
}
|
||||
else { true }
|
||||
};
|
||||
color
|
||||
}
|
||||
color
|
||||
}
|
||||
gray(parent) { black(parent) }
|
||||
black(parent) { black(parent) }
|
||||
@ -621,4 +631,4 @@ fn alli<A: copy send>(xs: [A], f: fn~(uint, A) -> bool) -> bool {
|
||||
}) {|x| x }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user