Skip to content

Commit c8db5a6

Browse files
committed
---
yaml --- r: 141295 b: refs/heads/try2 c: c33258b h: refs/heads/master i: 141293: e15b69a 141291: 7055834 141287: f29d134 141279: 58cac24 v: v3
1 parent aa52499 commit c8db5a6

36 files changed

+831
-373
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 32c619916179ff373a145b3006c5c19362af9b15
8+
refs/heads/try2: c33258bee10590b2f388090d294e1720b2ebfb64
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/configure

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,11 +555,11 @@ then
555555
CFG_CLANG_VERSION=$("$CFG_CLANG" \
556556
--version \
557557
| grep version \
558-
| sed 's/.*\(version .*\)/\1/' \
558+
| sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \
559559
| cut -d ' ' -f 2)
560560

561561
case $CFG_CLANG_VERSION in
562-
(3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 4.0* | 4.1* | 4.2*)
562+
(3.0svn | 3.0 | 3.1* | 3.2* | 3.3*)
563563
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
564564
CFG_C_COMPILER="clang"
565565
;;

branches/try2/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/try2/src/libextra/arc.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* In this example, a large vector of floats is shared between several tasks.
1818
* With simple pipes, without ARC, a copy would have to be made for each task.
1919
*
20-
* ~~~
20+
* ~~~ {.rust}
2121
* extern mod std;
2222
* use std::arc;
2323
* let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random());
@@ -370,7 +370,10 @@ pub impl<T:Const + Owned> RWARC<T> {
370370
* See sync::rwlock.write_downgrade(). The RWWriteMode token must be used
371371
* to obtain the &mut T, and can be transformed into a RWReadMode token by
372372
* calling downgrade(), after which a &T can be obtained instead.
373-
* ~~~
373+
*
374+
* # Example
375+
*
376+
* ~~~ {.rust}
374377
* do arc.write_downgrade |write_mode| {
375378
* do (&write_mode).write_cond |state, condvar| {
376379
* ... exclusive access with mutable state ...

branches/try2/src/libextra/base64.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ impl<'self> ToBase64 for &'self [u8] {
2828
/**
2929
* Turn a vector of `u8` bytes into a base64 string.
3030
*
31-
* *Example*:
31+
* # Example
3232
*
33-
* ~~~~
33+
* ~~~ {.rust}
3434
* extern mod std;
3535
* use std::base64::ToBase64;
3636
*
3737
* fn main () {
3838
* let str = [52,32].to_base64();
3939
* println(fmt!("%s", str));
4040
* }
41-
* ~~~~
41+
* ~~~
4242
*/
4343
fn to_base64(&self) -> ~str {
4444
let mut s = ~"";
@@ -91,17 +91,17 @@ impl<'self> ToBase64 for &'self str {
9191
* Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
9292
*
9393
*
94-
* *Example*:
94+
* # Example
9595
*
96-
* ~~~~
96+
* ~~~ {.rust}
9797
* extern mod std;
9898
* use std::base64::ToBase64;
9999
*
100100
* fn main () {
101101
* let str = "Hello, World".to_base64();
102102
* println(fmt!("%s",str));
103103
* }
104-
* ~~~~
104+
* ~~~
105105
*
106106
*/
107107
fn to_base64(&self) -> ~str {
@@ -118,9 +118,9 @@ impl FromBase64 for ~[u8] {
118118
* Convert base64 `u8` vector into u8 byte values.
119119
* Every 4 encoded characters is converted into 3 octets, modulo padding.
120120
*
121-
* *Example*:
121+
* # Example
122122
*
123-
* ~~~~
123+
* ~~~ {.rust}
124124
* extern mod std;
125125
* use std::base64::ToBase64;
126126
* use std::base64::FromBase64;
@@ -131,7 +131,7 @@ impl FromBase64 for ~[u8] {
131131
* let bytes = str.from_base64();
132132
* println(fmt!("%?",bytes));
133133
* }
134-
* ~~~~
134+
* ~~~
135135
*/
136136
fn from_base64(&self) -> ~[u8] {
137137
if self.len() % 4u != 0u { fail!("invalid base64 length"); }
@@ -196,11 +196,11 @@ impl FromBase64 for ~str {
196196
* You can use the `from_bytes` function in `core::str`
197197
* to turn a `[u8]` into a string with characters corresponding to those values.
198198
*
199-
* *Example*:
199+
* # Example
200200
*
201201
* This converts a string literal to base64 and back.
202202
*
203-
* ~~~~
203+
* ~~~ {.rust}
204204
* extern mod std;
205205
* use std::base64::ToBase64;
206206
* use std::base64::FromBase64;
@@ -214,7 +214,7 @@ impl FromBase64 for ~str {
214214
* let result_str = str::from_bytes(bytes);
215215
* println(fmt!("%s",result_str));
216216
* }
217-
* ~~~~
217+
* ~~~
218218
*/
219219
fn from_base64(&self) -> ~[u8] {
220220
str::to_bytes(*self).from_base64()

branches/try2/src/libextra/deque.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,31 @@ pub impl<T> Deque<T> {
125125
self.hi = (self.hi + 1u) % self.elts.len();
126126
self.nelts += 1u;
127127
}
128+
129+
/// Reserve capacity for exactly `n` elements in the given deque,
130+
/// doing nothing if `self`'s capacity is already equal to or greater
131+
/// than the requested capacity
132+
///
133+
/// # Arguments
134+
///
135+
/// * n - The number of elements to reserve space for
136+
fn reserve(&mut self, n: uint) {
137+
vec::reserve(&mut self.elts, n);
138+
}
139+
140+
/// Reserve capacity for at least `n` elements in the given deque,
141+
/// over-allocating in case the caller needs to reserve additional
142+
/// space.
143+
///
144+
/// Do nothing if `self`'s capacity is already equal to or greater
145+
/// than the requested capacity.
146+
///
147+
/// # Arguments
148+
///
149+
/// * n - The number of elements to reserve space for
150+
fn reserve_at_least(&mut self, n: uint) {
151+
vec::reserve_at_least(&mut self.elts, n);
152+
}
128153
}
129154

130155
/// Grow is only called on full elts, so nelts is also len(elts), unlike
@@ -149,6 +174,7 @@ mod tests {
149174
use super::*;
150175
use core::cmp::Eq;
151176
use core::kinds::Copy;
177+
use core::vec::capacity;
152178

153179
#[test]
154180
fn test_simple() {
@@ -328,4 +354,29 @@ mod tests {
328354
}
329355

330356
}
357+
358+
#[test]
359+
fn test_reserve() {
360+
let mut d = Deque::new();
361+
d.add_back(0u64);
362+
d.reserve(50);
363+
assert_eq!(capacity(&mut d.elts), 50);
364+
let mut d = Deque::new();
365+
d.add_back(0u32);
366+
d.reserve(50);
367+
assert_eq!(capacity(&mut d.elts), 50);
368+
}
369+
370+
#[test]
371+
fn test_reserve_at_least() {
372+
let mut d = Deque::new();
373+
d.add_back(0u64);
374+
d.reserve_at_least(50);
375+
assert_eq!(capacity(&mut d.elts), 64);
376+
let mut d = Deque::new();
377+
d.add_back(0u32);
378+
d.reserve_at_least(50);
379+
assert_eq!(capacity(&mut d.elts), 64);
380+
}
381+
331382
}

branches/try2/src/libextra/flatpipes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ports and channels.
2525
2626
This example sends boxed integers across tasks using serialization.
2727
28-
~~~
28+
~~~ {.rust}
2929
let (port, chan) = serial::pipe_stream();
3030
3131
do task::spawn || {

branches/try2/src/libextra/future.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
* # Example
1616
*
17-
* ~~~
17+
* ~~~ {.rust}
1818
* # fn fib(n: uint) -> uint {42};
1919
* # fn make_a_sandwich() {};
2020
* let mut delayed_fib = std::future::spawn (|| fib(5000) );

branches/try2/src/libextra/net_tcp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint)
466466
* Here, the `new_conn` is used in conjunction with `accept` from within
467467
* a task spawned by the `new_connect_cb` passed into `listen`
468468
*
469-
* ~~~~~~~~~~~
469+
* ~~~ {.rust}
470470
* do net::tcp::listen(remote_ip, remote_port, backlog, iotask,
471471
* // this callback is ran once after the connection is successfully
472472
* // set up
@@ -497,7 +497,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint)
497497
* None => ()
498498
* }
499499
* };
500-
* ~~~~~~~~~~~
500+
* ~~~
501501
*
502502
* # Arguments
503503
*

branches/try2/src/libextra/sync.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,10 @@ pub impl RWlock {
545545
* the meantime (such as unlocking and then re-locking as a reader would
546546
* do). The block takes a "write mode token" argument, which can be
547547
* transformed into a "read mode token" by calling downgrade(). Example:
548-
* ~~~
548+
*
549+
* # Example
550+
*
551+
* ~~~ {.rust}
549552
* do lock.write_downgrade |write_mode| {
550553
* do (&write_mode).write_cond |condvar| {
551554
* ... exclusive access ...

branches/try2/src/libextra/time.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -22,11 +22,11 @@ pub mod rustrt {
2222
pub unsafe fn precise_time_ns(ns: &mut u64);
2323

2424
pub unsafe fn rust_tzset();
25-
// FIXME: The i64 values can be passed by-val when #2064 is fixed.
25+
2626
pub unsafe fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm);
2727
pub unsafe fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm);
28-
pub unsafe fn rust_timegm(tm: &Tm, sec: &mut i64);
29-
pub unsafe fn rust_mktime(tm: &Tm, sec: &mut i64);
28+
pub unsafe fn rust_timegm(tm: &Tm) -> i64;
29+
pub unsafe fn rust_mktime(tm: &Tm) -> i64;
3030
}
3131
}
3232

@@ -177,12 +177,11 @@ pub impl Tm {
177177
/// Convert time to the seconds from January 1, 1970
178178
fn to_timespec(&self) -> Timespec {
179179
unsafe {
180-
let mut sec = 0i64;
181-
if self.tm_gmtoff == 0_i32 {
182-
rustrt::rust_timegm(self, &mut sec);
183-
} else {
184-
rustrt::rust_mktime(self, &mut sec);
185-
}
180+
let sec = match self.tm_gmtoff {
181+
0_i32 => rustrt::rust_timegm(self),
182+
_ => rustrt::rust_mktime(self)
183+
};
184+
186185
Timespec::new(sec, self.tm_nsec)
187186
}
188187
}

0 commit comments

Comments
 (0)