Skip to content

Commit 2bf9740

Browse files
author
Olivier Saut
committed
---
yaml --- r: 73462 b: refs/heads/dist-snap c: dea6677 h: refs/heads/master v: v3
1 parent b10e769 commit 2bf9740

File tree

4 files changed

+75
-54
lines changed

4 files changed

+75
-54
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
99
refs/heads/incoming: b50030718cf28f2a5a81857a26b57442734fe854
10-
refs/heads/dist-snap: 1f8c4b096da8d7c6436038730fa4a862e1ac91f5
10+
refs/heads/dist-snap: dea667725137368dd9c928bae3c091b9ccf42e67
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1313
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/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/dist-snap/src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,20 +1694,7 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt,
16941694
vec::from_fn(args.len(), |i| {
16951695
unsafe {
16961696
let arg_n = first_real_arg + i;
1697-
let arg = &args[i];
1698-
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint);
1699-
1700-
// Mark `&mut T` as no-alias, as the borrowck pass ensures it's true
1701-
match arg.ty.node {
1702-
ast::ty_rptr(_, mt) => {
1703-
if mt.mutbl == ast::m_mutbl {
1704-
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
1705-
}
1706-
}
1707-
_ => {}
1708-
}
1709-
1710-
llarg
1697+
llvm::LLVMGetParam(cx.llfn, arg_n as c_uint)
17111698
}
17121699
})
17131700
}

branches/dist-snap/src/librustdoc/markdown_pass.rs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -451,32 +451,16 @@ fn write_variants(
451451
fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) {
452452
assert!(doc.sig.is_some());
453453
let sig = (&doc.sig).get();
454-
455-
// space out list items so they all end up within paragraph elements
456-
ctxt.w.put_line(~"");
457-
458454
match copy doc.desc {
459455
Some(desc) => {
460-
ctxt.w.put_line(list_item_indent(fmt!("* `%s` - %s", sig, desc)));
456+
ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc));
461457
}
462458
None => {
463459
ctxt.w.put_line(fmt!("* `%s`", sig));
464460
}
465461
}
466462
}
467463

468-
fn list_item_indent(item: &str) -> ~str {
469-
let mut indented = ~[];
470-
for str::each_line_any(item) |line| {
471-
indented.push(line);
472-
}
473-
474-
// separate markdown elements within `*` lists must be indented by four
475-
// spaces, or they will escape the list context. indenting everything
476-
// seems fine though.
477-
str::connect_slices(indented, "\n ")
478-
}
479-
480464
fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) {
481465
write_common(ctxt, doc.desc(), doc.sections());
482466
write_methods(ctxt, doc.methods);
@@ -823,9 +807,7 @@ mod test {
823807
assert!(str::contains(
824808
markdown,
825809
"\n\n#### Variants\n\
826-
\n\
827810
\n* `b` - test\
828-
\n\
829811
\n* `c` - test\n\n"));
830812
}
831813

@@ -835,24 +817,7 @@ mod test {
835817
assert!(str::contains(
836818
markdown,
837819
"\n\n#### Variants\n\
838-
\n\
839820
\n* `b`\
840-
\n\
841-
\n* `c`\n\n"));
842-
}
843-
844-
#[test]
845-
fn should_write_variant_list_with_indent() {
846-
let markdown = render(
847-
~"enum a { #[doc = \"line 1\\n\\nline 2\"] b, c }");
848-
assert!(str::contains(
849-
markdown,
850-
"\n\n#### Variants\n\
851-
\n\
852-
\n* `b` - line 1\
853-
\n \
854-
\n line 2\
855-
\n\
856821
\n* `c`\n\n"));
857822
}
858823

@@ -862,9 +827,7 @@ mod test {
862827
assert!(str::contains(
863828
markdown,
864829
"\n\n#### Variants\n\
865-
\n\
866830
\n* `b(int)`\
867-
\n\
868831
\n* `c(int)` - a\n\n"));
869832
}
870833

0 commit comments

Comments
 (0)