Skip to content

Commit aa2efc0

Browse files
committed
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.
1 parent 3f0358b commit aa2efc0

File tree

4 files changed

+88
-27
lines changed

4 files changed

+88
-27
lines changed

src/libstd/arc.rs

+42-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#[doc = "An atomically reference counted wrapper that can be used to
22
share immutable data between tasks."]
33

4-
export arc, get, clone;
4+
import comm::{port, chan, methods};
5+
6+
export arc, get, clone, shared_arc, get_arc;
57

68
#[abi = "cdecl"]
79
native mod rustrt {
@@ -14,12 +16,12 @@ native mod rustrt {
1416
-> libc::intptr_t;
1517
}
1618

17-
type arc_data<T> = {
19+
type arc_data<T: const> = {
1820
mut count: libc::intptr_t,
1921
data: T
2022
};
2123

22-
resource arc_destruct<T>(data: *libc::c_void) {
24+
resource arc_destruct<T: const>(data: *libc::c_void) {
2325
unsafe {
2426
let data: ~arc_data<T> = unsafe::reinterpret_cast(data);
2527
let ref_ptr = &mut data.count;
@@ -34,10 +36,10 @@ resource arc_destruct<T>(data: *libc::c_void) {
3436
}
3537
}
3638

37-
type arc<T> = arc_destruct<T>;
39+
type arc<T: const> = arc_destruct<T>;
3840

3941
#[doc="Create an atomically reference counted wrapper."]
40-
fn arc<T>(-data: T) -> arc<T> {
42+
fn arc<T: const>(-data: T) -> arc<T> {
4143
let data = ~{mut count: 1, data: data};
4244
unsafe {
4345
let ptr = unsafe::reinterpret_cast(data);
@@ -48,7 +50,7 @@ fn arc<T>(-data: T) -> arc<T> {
4850

4951
#[doc="Access the underlying data in an atomically reference counted
5052
wrapper."]
51-
fn get<T>(rc: &a.arc<T>) -> &a.T {
53+
fn get<T: const>(rc: &a.arc<T>) -> &a.T {
5254
unsafe {
5355
let ptr: ~arc_data<T> = unsafe::reinterpret_cast(**rc);
5456
// Cast us back into the correct region
@@ -63,11 +65,44 @@ fn get<T>(rc: &a.arc<T>) -> &a.T {
6365
The resulting two `arc` objects will point to the same underlying data
6466
object. However, one of the `arc` objects can be sent to another task,
6567
allowing them to share the underlying data."]
66-
fn clone<T>(rc: &arc<T>) -> arc<T> {
68+
fn clone<T: const>(rc: &arc<T>) -> arc<T> {
6769
unsafe {
6870
let ptr: ~arc_data<T> = unsafe::reinterpret_cast(**rc);
6971
rustrt::rust_atomic_increment(&mut ptr.count);
7072
unsafe::forget(ptr);
7173
}
7274
arc_destruct(**rc)
7375
}
76+
77+
// Convenience code for sharing arcs between tasks
78+
79+
enum proto<T: send const> {
80+
terminate,
81+
shared_get(comm::chan<arc::arc<T>>)
82+
}
83+
84+
resource shared_arc_res<T: send const>(c: comm::chan<proto<T>>) {
85+
c.send(terminate);
86+
}
87+
88+
fn shared_arc<T: send const>(-data: T) -> shared_arc_res<T> {
89+
let a = arc::arc(data);
90+
let c = task::spawn_listener::<proto<T>>() {|p, move a|
91+
let mut live = true;
92+
while live {
93+
alt p.recv() {
94+
terminate { live = false; }
95+
shared_get(cc) {
96+
cc.send(arc::clone(&a));
97+
}
98+
}
99+
}
100+
};
101+
shared_arc_res(c)
102+
}
103+
104+
fn get_arc<T: send const>(c: comm::chan<proto<T>>) -> arc::arc<T> {
105+
let p = port();
106+
c.send(shared_get(chan(p)));
107+
p.recv()
108+
}

src/rustc/middle/trans/base.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,14 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
20282028
}
20292029
});
20302030

2031+
#debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?",
2032+
fn_id, ty::item_path_str(ccx.tcx, fn_id),
2033+
real_substs.map({|s| ty_to_str(ccx.tcx, s)}),
2034+
substs.map({|s| ty_to_str(ccx.tcx, s)})];
2035+
2036+
for real_substs.each() {|s| assert !ty::type_has_params(s); };
2037+
for substs.each() {|s| assert !ty::type_has_params(s); };
2038+
20312039
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
20322040
let hash_id = make_mono_id(ccx, fn_id, substs, vtables, some(param_uses));
20332041
if vec::any(hash_id.params,
@@ -4231,6 +4239,7 @@ fn alloc_ty(bcx: block, t: ty::t) -> ValueRef {
42314239
let _icx = bcx.insn_ctxt("alloc_ty");
42324240
let ccx = bcx.ccx();
42334241
let llty = type_of(ccx, t);
4242+
if ty::type_has_params(t) { log(error, ty_to_str(ccx.tcx, t)); }
42344243
assert !ty::type_has_params(t);
42354244
let val = alloca(bcx, llty);
42364245
ret val;

src/rustc/middle/trans/shape.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import syntax::ast;
1414
import syntax::ast_util::{dummy_sp, new_def_hash};
1515
import syntax::util::interner;
1616
import util::common;
17+
import util::ppaux::ty_to_str;
1718
import syntax::codemap::span;
1819
import dvec::{dvec, extensions};
1920

@@ -445,6 +446,11 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
445446
s
446447
}
447448
ty::ty_res(did, raw_subt, substs) {
449+
#debug["ty_res(%?, %?, %?)",
450+
did,
451+
ty_to_str(ccx.tcx, raw_subt),
452+
substs.tps.map({|t| ty_to_str(ccx.tcx, t) })];
453+
for substs.tps.each() {|t| assert !ty::type_has_params(t); }
448454
let subt = ty::subst(ccx.tcx, substs, raw_subt);
449455
let tps = substs.tps;
450456
let ri = {did: did, tps: tps};
@@ -589,8 +595,9 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
589595
let mut dtors = [];
590596
let len = interner::len(ccx.shape_cx.resources);
591597
for uint::range(0u, len) {|i|
592-
let ri = interner::get(ccx.shape_cx.resources, i);
593-
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
598+
let ri = interner::get(ccx.shape_cx.resources, i);
599+
for ri.tps.each() {|s| assert !ty::type_has_params(s); }
600+
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
594601
}
595602
ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
596603
}

src/test/bench/graph500-bfs.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// xfail-test :(
2+
13
/**
24
35
An implementation of the Graph500 Bread First Search problem in Rust.
@@ -10,6 +12,7 @@ import std::map;
1012
import std::map::hashmap;
1113
import std::deque;
1214
import std::deque::t;
15+
import std::arc;
1316
import io::writer_util;
1417
import comm::*;
1518
import int::abs;
@@ -264,34 +267,41 @@ fn pbfs(graph: graph, key: node_id) -> bfs_result {
264267
}
265268
}
266269

270+
let graph_arc = arc::shared_arc(copy graph);
271+
let graph = *graph_arc;
272+
267273
let mut i = 0u;
268274
while par::any(colors, is_gray) {
269275
// Do the BFS.
270276
log(info, #fmt("PBFS iteration %?", i));
271277
i += 1u;
272278
let old_len = colors.len();
273-
let pc = ptr::addr_of(colors);
274-
let pg = ptr::addr_of(graph);
279+
280+
let colors_arc = arc::shared_arc(copy colors);
281+
let color = *colors_arc;
282+
275283
colors = par::mapi(colors) {|i, c|
276284
let c : color = c;
285+
let colors = &arc::get_arc(color);
286+
let colors : [color] = *arc::get(colors);
287+
let graph = &arc::get_arc(graph);
288+
let graph : graph = *arc::get(graph);
277289
alt c {
278290
white {
279-
unsafe {
280-
let i = i as node_id;
281-
282-
let neighbors = &(*pg)[i];
283-
284-
let mut color = white;
285-
286-
(*neighbors).each() {|k|
287-
if is_gray((*pc)[k]) {
288-
color = gray(k);
289-
false
290-
}
291-
else { true }
291+
let i = i as node_id;
292+
293+
let neighbors = graph[i];
294+
295+
let mut color = white;
296+
297+
neighbors.each() {|k|
298+
if is_gray(colors[k]) {
299+
color = gray(k);
300+
false
301+
}
302+
else { true }
292303
};
293-
color
294-
}
304+
color
295305
}
296306
gray(parent) { black(parent) }
297307
black(parent) { black(parent) }
@@ -621,4 +631,4 @@ fn alli<A: copy send>(xs: [A], f: fn~(uint, A) -> bool) -> bool {
621631
}) {|x| x }
622632
}
623633

624-
}
634+
}

0 commit comments

Comments
 (0)