@@ -284,7 +284,7 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() );
284
284
# fn some_expensive_computation(_i: uint) -> int { 42 }
285
285
~~~
286
286
287
- ## Futures
287
+ ## Backgrounding computations: Futures
288
288
With ` extra::future ` , rust has a mechanism for requesting a computation and getting the result
289
289
later.
290
290
@@ -329,6 +329,77 @@ fn main() {
329
329
}
330
330
~~~
331
331
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
+
332
403
# Handling task failure
333
404
334
405
Rust has a built-in mechanism for raising exceptions. The ` fail!() ` macro
0 commit comments