Skip to content

Commit 1737da5

Browse files
committed
---
yaml --- r: 80986 b: refs/heads/snap-stage3 c: e98bd9b h: refs/heads/master v: v3
1 parent 79e1f51 commit 1737da5

File tree

5 files changed

+668
-1
lines changed

5 files changed

+668
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: e753618b6b9cbf41434fa566d1d3c7d15c86c4f7
4+
refs/heads/snap-stage3: e98bd9bb680c1ac673f4e5e227a57e5adfc7343c
55
refs/heads/try: 70152ff55722878cde684ee6462c14c65f2c4729
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libextra/extra.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub mod glob;
8989
pub mod term;
9090
pub mod time;
9191
pub mod arena;
92+
pub mod par;
9293
pub mod base64;
9394
pub mod rl;
9495
pub mod workcache;
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
use std::cast;
13+
use std::num;
14+
use std::ptr;
15+
use std::sys;
16+
use std::vec;
17+
use future::Future;
18+
19+
/**
20+
* The maximum number of tasks this module will spawn for a single
21+
* operation.
22+
*/
23+
static MAX_TASKS : uint = 32u;
24+
25+
/// The minimum number of elements each task will process.
26+
static MIN_GRANULARITY : uint = 1024u;
27+
28+
/**
29+
* An internal helper to map a function over a large vector and
30+
* return the intermediate results.
31+
*
32+
* This is used to build most of the other parallel vector functions,
33+
* like map or alli.
34+
*/
35+
fn map_slices<A:Clone + Send,B:Clone + Send>(
36+
xs: &[A],
37+
f: &fn() -> ~fn(uint, v: &[A]) -> B)
38+
-> ~[B] {
39+
40+
let len = xs.len();
41+
if len < MIN_GRANULARITY {
42+
info!("small slice");
43+
// This is a small vector, fall back on the normal map.
44+
~[f()(0u, xs)]
45+
} else {
46+
let num_tasks = num::min(MAX_TASKS, len / MIN_GRANULARITY);
47+
48+
let items_per_task = len / num_tasks;
49+
50+
let mut futures = ~[];
51+
let mut base = 0u;
52+
info!("spawning tasks");
53+
while base < len {
54+
let end = num::min(len, base + items_per_task);
55+
do xs.as_imm_buf |p, _len| {
56+
let f = f();
57+
let base = base;
58+
let f = do Future::spawn() || {
59+
unsafe {
60+
let len = end - base;
61+
let slice = (ptr::offset(p, base as int),
62+
len * sys::size_of::<A>());
63+
info!("pre-slice: %?", (base, slice));
64+
let slice : &[A] =
65+
cast::transmute(slice);
66+
info!("slice: %?", (base, slice.len(), end - base));
67+
assert_eq!(slice.len(), end - base);
68+
f(base, slice)
69+
}
70+
};
71+
futures.push(f);
72+
};
73+
base += items_per_task;
74+
}
75+
info!("tasks spawned");
76+
77+
info!("num_tasks: %?", (num_tasks, futures.len()));
78+
assert_eq!(num_tasks, futures.len());
79+
80+
do futures.move_iter().map |ys| {
81+
let mut ys = ys;
82+
ys.get()
83+
}.collect()
84+
}
85+
}
86+
87+
/// A parallel version of map.
88+
pub fn map<A:Clone + Send,B:Clone + Send>(
89+
xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] {
90+
vec::concat(map_slices(xs, || {
91+
let f = fn_factory();
92+
let result: ~fn(uint, &[A]) -> ~[B] =
93+
|_, slice| slice.iter().map(|x| f(x)).collect();
94+
result
95+
}))
96+
}
97+
98+
/// A parallel version of mapi.
99+
pub fn mapi<A:Clone + Send,B:Clone + Send>(
100+
xs: &[A],
101+
fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B] {
102+
let slices = map_slices(xs, || {
103+
let f = fn_factory();
104+
let result: ~fn(uint, &[A]) -> ~[B] = |base, slice| {
105+
slice.iter().enumerate().map(|(i, x)| {
106+
f(i + base, x)
107+
}).collect()
108+
};
109+
result
110+
});
111+
let r = vec::concat(slices);
112+
info!("%?", (r.len(), xs.len()));
113+
assert_eq!(r.len(), xs.len());
114+
r
115+
}
116+
117+
/// Returns true if the function holds for all elements in the vector.
118+
pub fn alli<A:Clone + Send>(
119+
xs: &[A],
120+
fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool
121+
{
122+
let mapped = map_slices(xs, || {
123+
let f = fn_factory();
124+
let result: ~fn(uint, &[A]) -> bool = |base, slice| {
125+
slice.iter().enumerate().all(|(i, x)| f(i + base, x))
126+
};
127+
result
128+
});
129+
mapped.iter().all(|&x| x)
130+
}
131+
132+
/// Returns true if the function holds for any elements in the vector.
133+
pub fn any<A:Clone + Send>(
134+
xs: &[A],
135+
fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
136+
let mapped = map_slices(xs, || {
137+
let f = fn_factory();
138+
let result: ~fn(uint, &[A]) -> bool = |_, slice| slice.iter().any(f);
139+
result
140+
});
141+
mapped.iter().any(|&x| x)
142+
}

branches/snap-stage3/src/libstd/vec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
925925
}
926926

927927
#[inline]
928+
/// Returns an iterator over the vector
928929
fn iter(self) -> VecIterator<'self, T> {
929930
unsafe {
930931
let p = vec::raw::to_ptr(self);
@@ -941,6 +942,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
941942
}
942943

943944
#[inline]
945+
/// Returns a reversed iterator over a vector
944946
fn rev_iter(self) -> RevIterator<'self, T> {
945947
self.iter().invert()
946948
}
@@ -1931,6 +1933,7 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
19311933
}
19321934

19331935
#[inline]
1936+
/// Returns an iterator that allows modifying each value
19341937
fn mut_iter(self) -> VecMutIterator<'self, T> {
19351938
unsafe {
19361939
let p = vec::raw::to_mut_ptr(self);
@@ -1947,6 +1950,7 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
19471950
}
19481951

19491952
#[inline]
1953+
/// Returns a reversed iterator that allows modifying each value
19501954
fn mut_rev_iter(self) -> MutRevIterator<'self, T> {
19511955
self.mut_iter().invert()
19521956
}
@@ -1988,11 +1992,13 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
19881992
}
19891993

19901994
#[inline]
1995+
/// Returns an unsafe mutable pointer to the element in index
19911996
unsafe fn unsafe_mut_ref(self, index: uint) -> *mut T {
19921997
ptr::mut_offset(self.repr().data as *mut T, index as int)
19931998
}
19941999

19952000
#[inline]
2001+
/// Unsafely sets the element in index to the value
19962002
unsafe fn unsafe_set(self, index: uint, val: T) {
19972003
*self.unsafe_mut_ref(index) = val;
19982004
}

0 commit comments

Comments
 (0)