Skip to content

Commit 0f9e141

Browse files
committed
---
yaml --- r: 60763 b: refs/heads/auto c: 26fb16e h: refs/heads/master i: 60761: 9dcbe48 60759: 014943e v: v3
1 parent 1fa7b32 commit 0f9e141

File tree

5 files changed

+79
-25
lines changed

5 files changed

+79
-25
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1414
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1515
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1616
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
17-
refs/heads/auto: 4521c347757329d4166e1a1c0239de2fcdd508e9
17+
refs/heads/auto: 26fb16e36fe5843b745fa1f3a1b333352300798c
1818
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1919
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c

branches/auto/doc/tutorial-tasks.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() );
284284
# fn some_expensive_computation(_i: uint) -> int { 42 }
285285
~~~
286286

287-
## Futures
287+
## Backgrounding computations: Futures
288288
With `extra::future`, rust has a mechanism for requesting a computation and getting the result
289289
later.
290290

@@ -329,6 +329,77 @@ fn main() {
329329
}
330330
~~~
331331

332+
## Sharing immutable data without copy: ARC
333+
334+
To share immutable data between tasks, a first approach would be to only use pipes as we have seen
335+
previously. A copy of the data to share would then be made for each task. In some cases, this would
336+
add up to a significant amount of wasted memory and would require copying the same data more than
337+
necessary.
338+
339+
To tackle this issue, one can use an Atomically Reference Counted wrapper (`ARC`) as implemented in
340+
the `extra` library of Rust. With an ARC, the data will no longer be copied for each task. The ARC
341+
acts as a reference to the shared data and only this reference is shared and cloned.
342+
343+
Here is a small example showing how to use ARCs. We wish to run concurrently several computations on
344+
a single large vector of floats. Each task needs the full vector to perform its duty.
345+
~~~
346+
use extra::arc::ARC;
347+
348+
fn pnorm(nums: &~[float], p: uint) -> float {
349+
(vec::foldl(0.0, *nums, |a,b| a+(*b).pow(p as float) )).pow(1f / (p as float))
350+
}
351+
352+
fn main() {
353+
let numbers=vec::from_fn(1000000, |_| rand::random::<float>());
354+
println(fmt!("Inf-norm = %?", numbers.max()));
355+
356+
let numbers_arc = ARC(numbers);
357+
358+
for uint::range(1,10) |num| {
359+
let (port, chan) = stream();
360+
chan.send(numbers_arc.clone());
361+
362+
do spawn {
363+
let local_arc : ARC<~[float]> = port.recv();
364+
let task_numbers = local_arc.get();
365+
println(fmt!("%u-norm = %?", num, pnorm(task_numbers, num)));
366+
}
367+
}
368+
}
369+
~~~
370+
371+
The function `pnorm` performs a simple computation on the vector (it computes the sum of its items
372+
at the power given as argument and takes the inverse power of this value). The ARC on the vector is
373+
created by the line
374+
~~~
375+
# use extra::arc::ARC;
376+
# let numbers=vec::from_fn(1000000, |_| rand::random::<float>());
377+
let numbers_arc=ARC(numbers);
378+
~~~
379+
and a clone of it is sent to each task
380+
~~~
381+
# use extra::arc::ARC;
382+
# let numbers=vec::from_fn(1000000, |_| rand::random::<float>());
383+
# let numbers_arc = ARC(numbers);
384+
# let (port, chan) = stream();
385+
chan.send(numbers_arc.clone());
386+
~~~
387+
copying only the wrapper and not its contents.
388+
389+
Each task recovers the underlying data by
390+
~~~
391+
# use extra::arc::ARC;
392+
# let numbers=vec::from_fn(1000000, |_| rand::random::<float>());
393+
# let numbers_arc=ARC(numbers);
394+
# let (port, chan) = stream();
395+
# chan.send(numbers_arc.clone());
396+
# let local_arc : ARC<~[float]> = port.recv();
397+
let task_numbers = local_arc.get();
398+
~~~
399+
and can use it as if it were local.
400+
401+
The `arc` module also implements ARCs around mutable data that are not covered here.
402+
332403
# Handling task failure
333404

334405
Rust has a built-in mechanism for raising exceptions. The `fail!()` macro

branches/auto/src/libextra/smallintmap.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,7 @@ impl Set<uint> for SmallIntSet {
246246
fn symmetric_difference(&self,
247247
other: &SmallIntSet,
248248
f: &fn(&uint) -> bool) -> bool {
249-
let len = cmp::max(self.map.v.len() ,other.map.v.len());
250-
251-
for uint::range(0, len) |i| {
252-
if self.contains(&i) ^ other.contains(&i) {
253-
if !f(&i) { return false; }
254-
}
255-
}
256-
return true;
249+
self.difference(other, f) && other.difference(self, f)
257250
}
258251

259252
/// Visit the values representing the uintersection
@@ -263,14 +256,7 @@ impl Set<uint> for SmallIntSet {
263256

264257
/// Visit the values representing the union
265258
fn union(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
266-
let len = cmp::max(self.map.v.len() ,other.map.v.len());
267-
268-
for uint::range(0, len) |i| {
269-
if self.contains(&i) || other.contains(&i) {
270-
if !f(&i) { return false; }
271-
}
272-
}
273-
return true;
259+
self.each(f) && other.each(|v| self.contains(v) || f(v))
274260
}
275261
}
276262

branches/auto/src/librustc/middle/trans/base.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,9 +2339,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
23392339
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
23402340
23412341
let start_def_id = ccx.tcx.lang_items.start_fn();
2342-
if start_def_id.crate == ast::local_crate {
2343-
ccx.sess.bug("start lang item is never in the local crate")
2344-
} else {
2342+
if start_def_id.crate != ast::local_crate {
23452343
let start_fn_type = csearch::get_type(ccx.tcx,
23462344
start_def_id).ty;
23472345
trans_external_path(ccx, start_def_id, start_fn_type);
@@ -2358,8 +2356,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
23582356
let (start_fn, args) = if use_start_lang_item {
23592357
let start_def_id = ccx.tcx.lang_items.start_fn();
23602358
let start_fn = if start_def_id.crate == ast::local_crate {
2361-
ccx.sess.bug("start lang item is never in the local \
2362-
crate")
2359+
get_item_val(ccx, start_def_id.node)
23632360
} else {
23642361
let start_fn_type = csearch::get_type(ccx.tcx,
23652362
start_def_id).ty;

branches/auto/src/librustc/middle/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
907907

908908
type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
909909

910-
pub type node_type_table = @mut SmallIntMap<t>;
910+
pub type node_type_table = @mut HashMap<uint,t>;
911911

912912
fn mk_rcache() -> creader_cache {
913913
return @mut HashMap::new();
@@ -934,7 +934,7 @@ pub fn mk_ctxt(s: session::Session,
934934
def_map: dm,
935935
region_maps: region_maps,
936936
region_paramd_items: region_paramd_items,
937-
node_types: @mut SmallIntMap::new(),
937+
node_types: @mut HashMap::new(),
938938
node_type_substs: @mut HashMap::new(),
939939
trait_refs: @mut HashMap::new(),
940940
trait_defs: @mut HashMap::new(),

0 commit comments

Comments
 (0)