From aa2efc05ea9aae3016890d61793768952b81154e Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 25 May 2012 15:29:27 -0700 Subject: [PATCH] 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. --- src/libstd/arc.rs | 49 ++++++++++++++++++++++++++++----- src/rustc/middle/trans/base.rs | 9 ++++++ src/rustc/middle/trans/shape.rs | 11 ++++++-- src/test/bench/graph500-bfs.rs | 46 +++++++++++++++++++------------ 4 files changed, 88 insertions(+), 27 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 30c106298f5..ce9599762d0 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -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 = { +type arc_data = { mut count: libc::intptr_t, data: T }; -resource arc_destruct(data: *libc::c_void) { +resource arc_destruct(data: *libc::c_void) { unsafe { let data: ~arc_data = unsafe::reinterpret_cast(data); let ref_ptr = &mut data.count; @@ -34,10 +36,10 @@ resource arc_destruct(data: *libc::c_void) { } } -type arc = arc_destruct; +type arc = arc_destruct; #[doc="Create an atomically reference counted wrapper."] -fn arc(-data: T) -> arc { +fn arc(-data: T) -> arc { let data = ~{mut count: 1, data: data}; unsafe { let ptr = unsafe::reinterpret_cast(data); @@ -48,7 +50,7 @@ fn arc(-data: T) -> arc { #[doc="Access the underlying data in an atomically reference counted wrapper."] -fn get(rc: &a.arc) -> &a.T { +fn get(rc: &a.arc) -> &a.T { unsafe { let ptr: ~arc_data = unsafe::reinterpret_cast(**rc); // Cast us back into the correct region @@ -63,7 +65,7 @@ fn get(rc: &a.arc) -> &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(rc: &arc) -> arc { +fn clone(rc: &arc) -> arc { unsafe { let ptr: ~arc_data = unsafe::reinterpret_cast(**rc); rustrt::rust_atomic_increment(&mut ptr.count); @@ -71,3 +73,36 @@ fn clone(rc: &arc) -> arc { } arc_destruct(**rc) } + +// Convenience code for sharing arcs between tasks + +enum proto { + terminate, + shared_get(comm::chan>) +} + +resource shared_arc_res(c: comm::chan>) { + c.send(terminate); +} + +fn shared_arc(-data: T) -> shared_arc_res { + let a = arc::arc(data); + let c = task::spawn_listener::>() {|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(c: comm::chan>) -> arc::arc { + let p = port(); + c.send(shared_get(chan(p))); + p.recv() +} diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index d9eabaafce2..bdde26a0f82 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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; diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 931cd891718..b7da3b6821e 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -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); } diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 0979067c168..45f43f551ce 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -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(xs: [A], f: fn~(uint, A) -> bool) -> bool { }) {|x| x } } -} \ No newline at end of file +}