Update rustc to 00b112c45a604fa6f4b59af2a40c9deeadfdb7c6/rustc-1.0.0-dev.

This commit is contained in:
Josh Matthews 2015-01-15 13:26:44 -05:00 committed by Glenn Watson
parent ff8cbff810
commit 95fc29fa0d
255 changed files with 3550 additions and 3362 deletions

View file

@ -36,11 +36,7 @@ git = "https://github.com/servo/string-cache"
[dependencies.string_cache_macros]
git = "https://github.com/servo/string-cache"
[dependencies.url]
git = "https://github.com/servo/rust-url"
[dependencies.time]
git = "https://github.com/rust-lang/time"
[dependencies]
text_writer = "0.1.1"
url = "*"
time = "*"

View file

@ -58,7 +58,7 @@ const KEY_SHIFT: uint = 16;
/// positive rate for N == 100 and to quite bad false positive
/// rates for larger N.
pub struct BloomFilter {
counters: [u8, ..ARRAY_SIZE],
counters: [u8; ARRAY_SIZE],
}
impl Clone for BloomFilter {
@ -75,7 +75,7 @@ impl BloomFilter {
#[inline]
pub fn new() -> BloomFilter {
BloomFilter {
counters: [0, ..ARRAY_SIZE],
counters: [0; ARRAY_SIZE],
}
}
@ -101,7 +101,7 @@ impl BloomFilter {
#[inline]
pub fn clear(&mut self) {
self.counters = [0, ..ARRAY_SIZE]
self.counters = [0; ARRAY_SIZE]
}
#[inline]
@ -231,7 +231,7 @@ fn create_and_insert_some_stuff() {
let false_positives =
range(1001u, 2000).filter(|i| bf.might_contain(i)).count();
assert!(false_positives < 10) // 1%.
assert!(false_positives < 10); // 1%.
for i in range(0u, 100) {
bf.remove(&i);
@ -256,7 +256,7 @@ fn create_and_insert_some_stuff() {
mod bench {
extern crate test;
use std::hash::hash;
use std::hash::{hash, SipHasher};
use std::iter;
use super::BloomFilter;
@ -331,7 +331,7 @@ mod bench {
fn hash_a_uint(b: &mut test::Bencher) {
let mut i = 0u;
b.iter(|| {
test::black_box(hash(&i));
test::black_box(hash::<uint, SipHasher>(&i));
i += 1;
})
}

View file

@ -2,69 +2,59 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![old_impl_check]
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_state::DefaultState;
use rand::Rng;
use std::hash::{Hash, sip};
use std::hash::{Hash, SipHasher};
use std::iter::repeat;
use std::rand::task_rng;
use std::slice::Items;
use std::rand;
use std::slice::Iter;
#[cfg(test)]
use std::cell::Cell;
pub trait Cache<K: PartialEq, V: Clone> {
fn insert(&mut self, key: K, value: V);
fn find(&mut self, key: &K) -> Option<V>;
fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V;
fn evict_all(&mut self);
}
pub struct HashCache<K, V> {
entries: HashMap<K, V>,
entries: HashMap<K, V, DefaultState<SipHasher>>,
}
impl<K: Clone + PartialEq + Eq + Hash, V: Clone> HashCache<K,V> {
pub fn new() -> HashCache<K, V> {
impl<K, V> HashCache<K,V>
where K: Clone + PartialEq + Eq + Hash<SipHasher>,
V: Clone,
{
pub fn new() -> HashCache<K,V> {
HashCache {
entries: HashMap::new(),
entries: HashMap::with_hash_state(DefaultState),
}
}
}
impl<K: Clone + PartialEq + Eq + Hash, V: Clone> Cache<K,V> for HashCache<K,V> {
fn insert(&mut self, key: K, value: V) {
pub fn insert(&mut self, key: K, value: V) {
self.entries.insert(key, value);
}
fn find(&mut self, key: &K) -> Option<V> {
pub fn find(&self, key: &K) -> Option<V> {
match self.entries.get(key) {
Some(v) => Some(v.clone()),
None => None,
None => None,
}
}
fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V {
pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
match self.entries.entry(key.clone()) {
Occupied(occupied) => {
(*occupied.get()).clone()
}
Vacant(vacant) => {
(*vacant.set(blk(key))).clone()
(*vacant.insert(blk(key))).clone()
}
}
}
fn evict_all(&mut self) {
pub fn evict_all(&mut self) {
self.entries.clear();
}
}
impl<K,V> HashCache<K,V> where K: Clone + PartialEq + Eq + Hash, V: Clone {
pub fn find_equiv<'a,Sized? Q>(&'a self, key: &Q) -> Option<&'a V> where Q: Hash + Equiv<K> {
self.entries.find_equiv(key)
}
}
#[test]
@ -98,32 +88,30 @@ impl<K: Clone + PartialEq, V: Clone> LRUCache<K,V> {
let last_index = self.entries.len() - 1;
if pos != last_index {
let entry = self.entries.remove(pos);
self.entries.push(entry.unwrap());
self.entries.push(entry);
}
self.entries[last_index].ref1().clone()
self.entries[last_index].1.clone()
}
pub fn iter<'a>(&'a self) -> Items<'a,(K,V)> {
pub fn iter<'a>(&'a self) -> Iter<'a,(K,V)> {
self.entries.iter()
}
}
impl<K: Clone + PartialEq, V: Clone> Cache<K,V> for LRUCache<K,V> {
fn insert(&mut self, key: K, val: V) {
pub fn insert(&mut self, key: K, val: V) {
if self.entries.len() == self.cache_size {
self.entries.remove(0);
}
self.entries.push((key, val));
}
fn find(&mut self, key: &K) -> Option<V> {
match self.entries.iter().position(|&(ref k, _)| *k == *key) {
pub fn find(&mut self, key: &K) -> Option<V> {
match self.entries.iter().position(|&(ref k, _)| key == k) {
Some(pos) => Some(self.touch(pos)),
None => None,
}
}
fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V {
pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
match self.entries.iter().position(|&(ref k, _)| *k == *key) {
Some(pos) => self.touch(pos),
None => {
@ -134,7 +122,7 @@ impl<K: Clone + PartialEq, V: Clone> Cache<K,V> for LRUCache<K,V> {
}
}
fn evict_all(&mut self) {
pub fn evict_all(&mut self) {
self.entries.clear();
}
}
@ -145,9 +133,9 @@ pub struct SimpleHashCache<K,V> {
k1: u64,
}
impl<K:Clone+PartialEq+Hash,V:Clone> SimpleHashCache<K,V> {
impl<K:Clone+Eq+Hash<SipHasher>,V:Clone> SimpleHashCache<K,V> {
pub fn new(cache_size: uint) -> SimpleHashCache<K,V> {
let mut r = task_rng();
let mut r = rand::thread_rng();
SimpleHashCache {
entries: repeat(None).take(cache_size).collect(),
k0: r.gen(),
@ -161,35 +149,26 @@ impl<K:Clone+PartialEq+Hash,V:Clone> SimpleHashCache<K,V> {
}
#[inline]
fn bucket_for_key<Q:Hash>(&self, key: &Q) -> uint {
self.to_bucket(sip::hash_with_keys(self.k0, self.k1, key) as uint)
fn bucket_for_key<Q:Hash<SipHasher>>(&self, key: &Q) -> uint {
let mut hasher = SipHasher::new_with_keys(self.k0, self.k1);
key.hash(&mut hasher);
self.to_bucket(hasher.result() as uint)
}
#[inline]
pub fn find_equiv<'a,Q:Hash+Equiv<K>>(&'a self, key: &Q) -> Option<&'a V> {
let bucket_index = self.bucket_for_key(key);
match self.entries[bucket_index] {
Some((ref existing_key, ref value)) if key.equiv(existing_key) => Some(value),
_ => None,
}
}
}
impl<K:Clone+PartialEq+Hash,V:Clone> Cache<K,V> for SimpleHashCache<K,V> {
fn insert(&mut self, key: K, value: V) {
pub fn insert(&mut self, key: K, value: V) {
let bucket_index = self.bucket_for_key(&key);
self.entries[bucket_index] = Some((key, value));
}
fn find(&mut self, key: &K) -> Option<V> {
pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash<SipHasher> + Eq {
let bucket_index = self.bucket_for_key(key);
match self.entries[bucket_index] {
Some((ref existing_key, ref value)) if existing_key == key => Some((*value).clone()),
Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
_ => None,
}
}
fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V {
pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
match self.find(key) {
Some(value) => return value,
None => {}
@ -199,7 +178,7 @@ impl<K:Clone+PartialEq+Hash,V:Clone> Cache<K,V> for SimpleHashCache<K,V> {
value
}
fn evict_all(&mut self) {
pub fn evict_all(&mut self) {
for slot in self.entries.iter_mut() {
*slot = None
}

View file

@ -8,10 +8,9 @@ use cssparser::ToCss;
use std::ascii::AsciiExt;
use text_writer::TextWriter;
macro_rules! define_cursor {
($( $css: expr => $variant: ident = $value: expr, )+) => {
#[deriving(Clone, Copy, PartialEq, Eq, FromPrimitive, Show)]
#[derive(Clone, Copy, PartialEq, Eq, FromPrimitive, Show)]
#[repr(u8)]
pub enum Cursor {
$( $variant = $value ),+
@ -19,7 +18,7 @@ macro_rules! define_cursor {
impl Cursor {
pub fn from_css_keyword(keyword: &str) -> Result<Cursor, ()> {
match_ignore_ascii_case! { keyword:
match_ignore_ascii_case! { keyword,
$( concat!($css) => Ok(Cursor::$variant) ),+
_ => Err(())
}

View file

@ -54,12 +54,13 @@ pub use self::Stolen::{Empty, Abort, Data};
use alloc::arc::Arc;
use alloc::heap::{allocate, deallocate};
use std::kinds::marker;
use std::marker;
use std::mem::{forget, min_align_of, size_of, transmute};
use std::ptr;
use std::sync::Mutex;
use std::sync::atomic::{AtomicInt, AtomicPtr, SeqCst};
use std::sync::atomic::{AtomicInt, AtomicPtr};
use std::sync::atomic::Ordering::SeqCst;
// Once the queue is less than 1/K full, then it will be downsized. Note that
// the deque requires that this number be less than 2.
@ -97,7 +98,7 @@ pub struct Stealer<T> {
}
/// When stealing some data, this is an enumeration of the possible outcomes.
#[deriving(PartialEq, Show)]
#[derive(PartialEq, Show)]
pub enum Stolen<T> {
/// The deque was empty at the time of stealing
Empty,
@ -141,6 +142,8 @@ struct Buffer<T> {
log_size: uint,
}
unsafe impl<T: 'static> Send for Buffer<T> { }
impl<T: Send> BufferPool<T> {
/// Allocates a new buffer pool which in turn can be used to allocate new
/// deques.
@ -159,16 +162,16 @@ impl<T: Send> BufferPool<T> {
fn alloc(&mut self, bits: uint) -> Box<Buffer<T>> {
unsafe {
let mut pool = self.pool.lock();
let mut pool = self.pool.lock().unwrap();
match pool.iter().position(|x| x.size() >= (1 << bits)) {
Some(i) => pool.remove(i).unwrap(),
Some(i) => pool.remove(i),
None => box Buffer::new(bits)
}
}
}
fn free(&self, buf: Box<Buffer<T>>) {
let mut pool = self.pool.lock();
let mut pool = self.pool.lock().unwrap();
match pool.iter().position(|v| v.size() > buf.size()) {
Some(i) => pool.insert(i, buf),
None => pool.push(buf),
@ -403,256 +406,3 @@ impl<T: Send> Drop for Buffer<T> {
unsafe { deallocate(self.storage as *mut u8, size, min_align_of::<T>()) }
}
}
#[cfg(test)]
mod tests {
use super::{Data, BufferPool, Abort, Empty, Worker, Stealer};
use std::mem;
use rustrt::thread::Thread;
use std::rand;
use std::rand::Rng;
use std::sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, SeqCst,
AtomicUint, INIT_ATOMIC_UINT};
use std::vec;
#[test]
fn smoke() {
let pool = BufferPool::new();
let (w, s) = pool.deque();
assert_eq!(w.pop(), None);
assert_eq!(s.steal(), Empty);
w.push(1i);
assert_eq!(w.pop(), Some(1));
w.push(1);
assert_eq!(s.steal(), Data(1));
w.push(1);
assert_eq!(s.clone().steal(), Data(1));
}
#[test]
fn stealpush() {
static AMT: int = 100000;
let pool = BufferPool::<int>::new();
let (w, s) = pool.deque();
let t = Thread::start(proc() {
let mut left = AMT;
while left > 0 {
match s.steal() {
Data(i) => {
assert_eq!(i, 1);
left -= 1;
}
Abort | Empty => {}
}
}
});
for _ in range(0, AMT) {
w.push(1);
}
t.join();
}
#[test]
fn stealpush_large() {
static AMT: int = 100000;
let pool = BufferPool::<(int, int)>::new();
let (w, s) = pool.deque();
let t = Thread::start(proc() {
let mut left = AMT;
while left > 0 {
match s.steal() {
Data((1, 10)) => { left -= 1; }
Data(..) => panic!(),
Abort | Empty => {}
}
}
});
for _ in range(0, AMT) {
w.push((1, 10));
}
t.join();
}
fn stampede(w: Worker<Box<int>>, s: Stealer<Box<int>>,
nthreads: int, amt: uint) {
for _ in range(0, amt) {
w.push(box 20);
}
let mut remaining = AtomicUint::new(amt);
let unsafe_remaining: *mut AtomicUint = &mut remaining;
let threads = range(0, nthreads).map(|_| {
let s = s.clone();
Thread::start(proc() {
unsafe {
while (*unsafe_remaining).load(SeqCst) > 0 {
match s.steal() {
Data(box 20) => {
(*unsafe_remaining).fetch_sub(1, SeqCst);
}
Data(..) => panic!(),
Abort | Empty => {}
}
}
}
})
}).collect::<Vec<Thread<()>>>();
while remaining.load(SeqCst) > 0 {
match w.pop() {
Some(box 20) => { remaining.fetch_sub(1, SeqCst); }
Some(..) => panic!(),
None => {}
}
}
for thread in threads.into_iter() {
thread.join();
}
}
#[test]
fn run_stampede() {
let pool = BufferPool::<Box<int>>::new();
let (w, s) = pool.deque();
stampede(w, s, 8, 10000);
}
#[test]
fn many_stampede() {
static AMT: uint = 4;
let pool = BufferPool::<Box<int>>::new();
let threads = range(0, AMT).map(|_| {
let (w, s) = pool.deque();
Thread::start(proc() {
stampede(w, s, 4, 10000);
})
}).collect::<Vec<Thread<()>>>();
for thread in threads.into_iter() {
thread.join();
}
}
#[test]
fn stress() {
static AMT: int = 100000;
static NTHREADS: int = 8;
static DONE: AtomicBool = INIT_ATOMIC_BOOL;
static HITS: AtomicUint = INIT_ATOMIC_UINT;
let pool = BufferPool::<int>::new();
let (w, s) = pool.deque();
let threads = range(0, NTHREADS).map(|_| {
let s = s.clone();
Thread::start(proc() {
loop {
match s.steal() {
Data(2) => { HITS.fetch_add(1, SeqCst); }
Data(..) => panic!(),
_ if DONE.load(SeqCst) => break,
_ => {}
}
}
})
}).collect::<Vec<Thread<()>>>();
let mut rng = rand::task_rng();
let mut expected = 0;
while expected < AMT {
if rng.gen_range(0i, 3) == 2 {
match w.pop() {
None => {}
Some(2) => { HITS.fetch_add(1, SeqCst); },
Some(_) => panic!(),
}
} else {
expected += 1;
w.push(2);
}
}
while HITS.load(SeqCst) < AMT as uint {
match w.pop() {
None => {}
Some(2) => { HITS.fetch_add(1, SeqCst); },
Some(_) => panic!(),
}
}
DONE.store(true, SeqCst);
for thread in threads.into_iter() {
thread.join();
}
assert_eq!(HITS.load(SeqCst), expected as uint);
}
#[test]
#[cfg_attr(windows, ignore)] // apparently windows scheduling is weird?
fn no_starvation() {
static AMT: int = 10000;
static NTHREADS: int = 4;
static DONE: AtomicBool = INIT_ATOMIC_BOOL;
let pool = BufferPool::<(int, uint)>::new();
let (w, s) = pool.deque();
let (threads, hits) = vec::unzip(range(0, NTHREADS).map(|_| {
let s = s.clone();
let unique_box = box AtomicUint::new(0);
let thread_box = unsafe {
*mem::transmute::<&Box<AtomicUint>,
*const *mut AtomicUint>(&unique_box)
};
(Thread::start(proc() {
unsafe {
loop {
match s.steal() {
Data((1, 2)) => {
(*thread_box).fetch_add(1, SeqCst);
}
Data(..) => panic!(),
_ if DONE.load(SeqCst) => break,
_ => {}
}
}
}
}), unique_box)
}));
let mut rng = rand::task_rng();
let mut myhit = false;
'outer: loop {
for _ in range(0, rng.gen_range(0, AMT)) {
if !myhit && rng.gen_range(0i, 3) == 2 {
match w.pop() {
None => {}
Some((1, 2)) => myhit = true,
Some(_) => panic!(),
}
} else {
w.push((1, 2));
}
}
for slot in hits.iter() {
let amt = slot.load(SeqCst);
if amt == 0 { continue 'outer; }
}
if myhit {
break
}
}
DONE.store(true, SeqCst);
for thread in threads.into_iter() {
thread.join();
}
}
}

View file

@ -4,7 +4,8 @@
//! This file stolen wholesale from rustc/src/librustc/util/nodemap.rs
pub use std::hash::{Hash, Hasher, Writer};
use std::default::Default;
use std::hash::{Hasher, Writer};
/// A speedy hash algorithm for node ids and def ids. The hashmap in
/// libcollections by default uses SipHash which isn't quite as speedy as we
@ -13,33 +14,26 @@ pub use std::hash::{Hash, Hasher, Writer};
///
/// This uses FNV hashing, as described here:
/// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
#[deriving(Clone)]
pub struct FnvHasher;
#[allow(missing_copy_implementations)]
pub struct FnvHasher(u64);
pub struct FnvState(u64);
impl Hasher<FnvState> for FnvHasher {
fn hash<Sized? T: Hash<FnvState>>(&self, t: &T) -> u64 {
let mut state = FnvState(0xcbf29ce484222325);
t.hash(&mut state);
let FnvState(ret) = state;
return ret;
}
impl Default for FnvHasher {
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
}
impl Writer for FnvState {
impl Hasher for FnvHasher {
type Output = u64;
fn reset(&mut self) { *self = Default::default(); }
fn finish(&self) -> u64 { self.0 }
}
impl Writer for FnvHasher {
fn write(&mut self, bytes: &[u8]) {
let FnvState(mut hash) = *self;
let FnvHasher(mut hash) = *self;
for byte in bytes.iter() {
hash = hash ^ (*byte as u64);
hash = hash * 0x100000001b3;
}
*self = FnvState(hash);
*self = FnvHasher(hash);
}
}
#[inline(always)]
pub fn hash<T: Hash<FnvState>>(t: &T) -> u64 {
let s = FnvHasher;
s.hash(t)
}

View file

@ -8,11 +8,13 @@ use geom::rect::Rect;
use geom::size::Size2D;
use geom::num::Zero;
use serialize::{Encodable, Encoder};
use std::default::Default;
use std::i32;
use std::num::{Float, NumCast};
use std::num::{Float, NumCast, ToPrimitive};
use std::fmt;
use std::ops::{Add, Sub, Neg, Mul, Div, Rem};
use rustc_serialize::{Encoder, Encodable};
// Units for use with geom::length and geom::scale_factor.
@ -29,7 +31,7 @@ use std::fmt;
///
/// The ratio between ScreenPx and DevicePixel for a given display be found by calling
/// `servo::windowing::WindowMethods::hidpi_factor`.
#[deriving(Show, Copy)]
#[derive(Show, Copy)]
pub enum ScreenPx {}
/// One CSS "px" in the coordinate system of the "initial viewport":
@ -41,7 +43,7 @@ pub enum ScreenPx {}
///
/// At the default zoom level of 100%, one PagePx is equal to one ScreenPx. However, if the
/// document is zoomed in or out then this scale may be larger or smaller.
#[deriving(Encodable, Show, Copy)]
#[derive(RustcEncodable, Show, Copy)]
pub enum ViewportPx {}
/// One CSS "px" in the root coordinate system for the content document.
@ -50,7 +52,7 @@ pub enum ViewportPx {}
/// This is the mobile-style "pinch zoom" that enlarges content without reflowing it. When the
/// viewport zoom is not equal to 1.0, then the layout viewport is no longer the same physical size
/// as the viewable area.
#[deriving(Encodable, Show, Copy)]
#[derive(RustcEncodable, Show, Copy)]
pub enum PagePx {}
// In summary, the hierarchy of pixel units and the factors to convert from one to the next:
@ -65,7 +67,7 @@ pub enum PagePx {}
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
//
// FIXME: Implement Au using Length and ScaleFactor instead of a custom type.
#[deriving(Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord)]
#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord)]
pub struct Au(pub i32);
impl Default for Au {
@ -112,8 +114,8 @@ pub static MAX_RECT: Rect<Au> = Rect {
pub const MIN_AU: Au = Au(i32::MIN);
pub const MAX_AU: Au = Au(i32::MAX);
impl<E, S: Encoder<E>> Encodable<S, E> for Au {
fn encode(&self, e: &mut S) -> Result<(), E> {
impl Encodable for Au {
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
e.emit_f64(to_frac_px(*self))
}
}
@ -123,53 +125,65 @@ impl fmt::Show for Au {
write!(f, "{}px", to_frac_px(*self))
}}
impl Add<Au,Au> for Au {
impl Add for Au {
type Output = Au;
#[inline]
fn add(&self, other: &Au) -> Au {
let Au(s) = *self;
let Au(o) = *other;
fn add(self, other: Au) -> Au {
let Au(s) = self;
let Au(o) = other;
Au(s + o)
}
}
impl Sub<Au,Au> for Au {
impl Sub for Au {
type Output = Au;
#[inline]
fn sub(&self, other: &Au) -> Au {
let Au(s) = *self;
let Au(o) = *other;
fn sub(self, other: Au) -> Au {
let Au(s) = self;
let Au(o) = other;
Au(s - o)
}
}
impl Mul<i32, Au> for Au {
impl Mul<i32> for Au {
type Output = Au;
#[inline]
fn mul(&self, other: &i32) -> Au {
let Au(s) = *self;
Au(s * *other)
fn mul(self, other: i32) -> Au {
let Au(s) = self;
Au(s * other)
}
}
impl Div<i32, Au> for Au {
impl Div<i32> for Au {
type Output = Au;
#[inline]
fn div(&self, other: &i32) -> Au {
let Au(s) = *self;
Au(s / *other)
fn div(self, other: i32) -> Au {
let Au(s) = self;
Au(s / other)
}
}
impl Rem<i32, Au> for Au {
impl Rem<i32> for Au {
type Output = Au;
#[inline]
fn rem(&self, other: &i32) -> Au {
let Au(s) = *self;
Au(s % *other)
fn rem(self, other: i32) -> Au {
let Au(s) = self;
Au(s % other)
}
}
impl Neg<Au> for Au {
impl Neg for Au {
type Output = Au;
#[inline]
fn neg(&self) -> Au {
let Au(s) = *self;
fn neg(self) -> Au {
let Au(s) = self;
Au(-s)
}
}
@ -323,7 +337,7 @@ pub fn to_pt(au: Au) -> f64 {
/// Returns true if the rect contains the given point. Points on the top or left sides of the rect
/// are considered inside the rectangle, while points on the right or bottom sides of the rect are
/// not considered inside the rectangle.
pub fn rect_contains_point<T:PartialOrd + Add<T,T>>(rect: Rect<T>, point: Point2D<T>) -> bool {
pub fn rect_contains_point<T:PartialOrd + Add<T, Output=T>>(rect: Rect<T>, point: Point2D<T>) -> bool {
point.x >= rect.origin.x && point.x < rect.origin.x + rect.size.width &&
point.y >= rect.origin.y && point.y < rect.origin.y + rect.size.height
}

View file

@ -2,15 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![feature(default_type_params,macro_rules,unsafe_destructor)]
#![feature(unsafe_destructor)]
#![feature(plugin)]
#![feature(int_uint)]
#![feature(old_impl_check)]
#![feature(box_syntax)]
#![deny(unused_imports)]
#![deny(unused_variables)]
#![allow(missing_copy_implementations)]
#![allow(unstable)]
#![feature(phase)]
#[phase(plugin, link)]
extern crate log;
#[macro_use] extern crate log;
extern crate alloc;
extern crate collections;
@ -19,9 +22,9 @@ extern crate geom;
extern crate getopts;
extern crate layers;
extern crate libc;
#[no_link] #[macro_use] extern crate cssparser;
extern crate rand;
extern crate rustrt;
extern crate serialize;
extern crate "serialize" as rustc_serialize;
#[cfg(target_os="macos")]
extern crate task_info;
extern crate "time" as std_time;
@ -30,9 +33,9 @@ extern crate string_cache;
extern crate unicode;
extern crate url;
#[phase(plugin)] extern crate plugins;
#[phase(plugin)] extern crate string_cache_macros;
#[phase(plugin)] extern crate lazy_static;
#[no_link] #[macro_use] #[plugin]
extern crate string_cache_macros;
extern crate lazy_static;
use std::sync::Arc;

View file

@ -8,16 +8,17 @@ use geom::{Size2D, Point2D, SideOffsets2D, Rect};
use geom::num::Zero;
use std::cmp::{min, max};
use std::fmt::{Show, Formatter, Error};
use std::ops::{Add, Sub};
bitflags!(
#[deriving(Encodable, Copy)]
#[derive(RustcEncodable)]
flags WritingMode: u8 {
const FLAG_RTL = 1 << 0,
const FLAG_VERTICAL = 1 << 1,
const FLAG_VERTICAL_LR = 1 << 2,
const FLAG_SIDEWAYS_LEFT = 1 << 3
}
)
);
impl WritingMode {
#[inline]
@ -79,11 +80,11 @@ impl Show for WritingMode {
/// (in addition to taking it as a parameter to methods) and check it.
/// In non-debug builds, make this storage zero-size and the checks no-ops.
#[cfg(ndebug)]
#[deriving(Encodable, PartialEq, Eq, Clone, Copy)]
#[derive(RustcEncodable, PartialEq, Eq, Clone, Copy)]
struct DebugWritingMode;
#[cfg(not(ndebug))]
#[deriving(Encodable, PartialEq, Eq, Clone, Copy)]
#[derive(RustcEncodable, PartialEq, Eq, Clone, Copy)]
struct DebugWritingMode {
mode: WritingMode
}
@ -134,7 +135,7 @@ impl Show for DebugWritingMode {
/// A 2D size in flow-relative dimensions
#[deriving(Encodable, PartialEq, Eq, Clone, Copy)]
#[derive(RustcEncodable, PartialEq, Eq, Clone, Copy)]
pub struct LogicalSize<T> {
pub inline: T, // inline-size, a.k.a. logical width, a.k.a. measure
pub block: T, // block-size, a.k.a. logical height, a.k.a. extent
@ -143,7 +144,7 @@ pub struct LogicalSize<T> {
impl<T: Show> Show for LogicalSize<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
write!(formatter, "LogicalSize({}, i{}×b{})",
write!(formatter, "LogicalSize({:?}, i{:?}×b{:?})",
self.debug_writing_mode, self.inline, self.block)
}
}
@ -240,9 +241,11 @@ impl<T: Copy> LogicalSize<T> {
}
}
impl<T: Add<T, T>> Add<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
impl<T: Add<T, Output=T>> Add for LogicalSize<T> {
type Output = LogicalSize<T>;
#[inline]
fn add(&self, other: &LogicalSize<T>) -> LogicalSize<T> {
fn add(self, other: LogicalSize<T>) -> LogicalSize<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalSize {
debug_writing_mode: self.debug_writing_mode,
@ -252,9 +255,11 @@ impl<T: Add<T, T>> Add<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
}
}
impl<T: Sub<T, T>> Sub<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
impl<T: Sub<T, Output=T>> Sub for LogicalSize<T> {
type Output = LogicalSize<T>;
#[inline]
fn sub(&self, other: &LogicalSize<T>) -> LogicalSize<T> {
fn sub(self, other: LogicalSize<T>) -> LogicalSize<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalSize {
debug_writing_mode: self.debug_writing_mode,
@ -266,7 +271,7 @@ impl<T: Sub<T, T>> Sub<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
/// A 2D point in flow-relative dimensions
#[deriving(PartialEq, Encodable, Eq, Clone, Copy)]
#[derive(PartialEq, RustcEncodable, Eq, Clone, Copy)]
pub struct LogicalPoint<T> {
pub i: T, /// inline-axis coordinate
pub b: T, /// block-axis coordinate
@ -275,7 +280,7 @@ pub struct LogicalPoint<T> {
impl<T: Show> Show for LogicalPoint<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
write!(formatter, "LogicalPoint({} (i{}, b{}))",
write!(formatter, "LogicalPoint({:?} (i{:?}, b{:?}))",
self.debug_writing_mode, self.i, self.b)
}
}
@ -303,7 +308,7 @@ impl<T: Copy> LogicalPoint<T> {
}
}
impl<T: Copy + Sub<T, T>> LogicalPoint<T> {
impl<T: Copy + Sub<T, Output=T>> LogicalPoint<T> {
#[inline]
pub fn from_physical(mode: WritingMode, point: Point2D<T>, container_size: Size2D<T>)
-> LogicalPoint<T> {
@ -391,7 +396,7 @@ impl<T: Copy + Sub<T, T>> LogicalPoint<T> {
}
}
impl<T: Add<T,T>> LogicalPoint<T> {
impl<T: Copy + Add<T, Output=T>> LogicalPoint<T> {
/// This doesnt really makes sense,
/// but happens when dealing with multiple origins.
#[inline]
@ -405,9 +410,11 @@ impl<T: Add<T,T>> LogicalPoint<T> {
}
}
impl<T: Add<T,T>> Add<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
impl<T: Copy + Add<T,Output=T>> Add<LogicalSize<T>> for LogicalPoint<T> {
type Output = LogicalPoint<T>;
#[inline]
fn add(&self, other: &LogicalSize<T>) -> LogicalPoint<T> {
fn add(self, other: LogicalSize<T>) -> LogicalPoint<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalPoint {
debug_writing_mode: self.debug_writing_mode,
@ -417,9 +424,11 @@ impl<T: Add<T,T>> Add<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
}
}
impl<T: Sub<T,T>> Sub<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
impl<T: Copy + Sub<T,Output=T>> Sub<LogicalSize<T>> for LogicalPoint<T> {
type Output = LogicalPoint<T>;
#[inline]
fn sub(&self, other: &LogicalSize<T>) -> LogicalPoint<T> {
fn sub(self, other: LogicalSize<T>) -> LogicalPoint<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalPoint {
debug_writing_mode: self.debug_writing_mode,
@ -434,7 +443,7 @@ impl<T: Sub<T,T>> Sub<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
/// Represents the four sides of the margins, borders, or padding of a CSS box,
/// or a combination of those.
/// A positive "margin" can be added to a rectangle to obtain a bigger rectangle.
#[deriving(Encodable, PartialEq, Eq, Clone, Copy)]
#[derive(RustcEncodable, PartialEq, Eq, Clone, Copy)]
pub struct LogicalMargin<T> {
pub block_start: T,
pub inline_end: T,
@ -446,7 +455,7 @@ pub struct LogicalMargin<T> {
impl<T: Show> Show for LogicalMargin<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
write!(formatter,
"LogicalMargin({}, inline: {}..{} block: {}..{})",
"LogicalMargin({:?}, inline: {:?}..{:?} block: {:?}..{:?})",
self.debug_writing_mode,
self.inline_start,
self.inline_end,
@ -656,7 +665,7 @@ impl<T: PartialEq + Zero> LogicalMargin<T> {
}
}
impl<T: Add<T, T>> LogicalMargin<T> {
impl<T: Copy + Add<T, Output=T>> LogicalMargin<T> {
#[inline]
pub fn inline_start_end(&self) -> T {
self.inline_start + self.inline_end
@ -688,9 +697,11 @@ impl<T: Add<T, T>> LogicalMargin<T> {
}
}
impl<T: Add<T, T>> Add<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T> {
impl<T: Add<T, Output=T>> Add for LogicalMargin<T> {
type Output = LogicalMargin<T>;
#[inline]
fn add(&self, other: &LogicalMargin<T>) -> LogicalMargin<T> {
fn add(self, other: LogicalMargin<T>) -> LogicalMargin<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalMargin {
debug_writing_mode: self.debug_writing_mode,
@ -702,9 +713,11 @@ impl<T: Add<T, T>> Add<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T>
}
}
impl<T: Sub<T, T>> Sub<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T> {
impl<T: Sub<T, Output=T>> Sub for LogicalMargin<T> {
type Output = LogicalMargin<T>;
#[inline]
fn sub(&self, other: &LogicalMargin<T>) -> LogicalMargin<T> {
fn sub(self, other: LogicalMargin<T>) -> LogicalMargin<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalMargin {
debug_writing_mode: self.debug_writing_mode,
@ -718,7 +731,7 @@ impl<T: Sub<T, T>> Sub<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T>
/// A rectangle in flow-relative dimensions
#[deriving(Encodable, PartialEq, Eq, Clone, Copy)]
#[derive(RustcEncodable, PartialEq, Eq, Clone, Copy)]
pub struct LogicalRect<T> {
pub start: LogicalPoint<T>,
pub size: LogicalSize<T>,
@ -728,7 +741,7 @@ pub struct LogicalRect<T> {
impl<T: Show> Show for LogicalRect<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
write!(formatter,
"LogicalRect({}, i{}×b{}, @ (i{},b{}))",
"LogicalRect({:?}, i{:?}×b{:?}, @ (i{:?},b{:?}))",
self.debug_writing_mode,
self.size.inline,
self.size.block,
@ -772,7 +785,7 @@ impl<T: Copy> LogicalRect<T> {
}
}
impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> {
impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> LogicalRect<T> {
#[inline]
pub fn from_physical(mode: WritingMode, rect: Rect<T>, container_size: Size2D<T>)
-> LogicalRect<T> {
@ -881,7 +894,7 @@ impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> {
}
}
impl<T: Copy + Ord + Add<T, T> + Sub<T, T>> LogicalRect<T> {
impl<T: Copy + Ord + Add<T, Output=T> + Sub<T, Output=T>> LogicalRect<T> {
#[inline]
pub fn union(&self, other: &LogicalRect<T>) -> LogicalRect<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
@ -904,9 +917,11 @@ impl<T: Copy + Ord + Add<T, T> + Sub<T, T>> LogicalRect<T> {
}
}
impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> {
impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> Add<LogicalMargin<T>> for LogicalRect<T> {
type Output = LogicalRect<T>;
#[inline]
fn add(&self, other: &LogicalMargin<T>) -> LogicalRect<T> {
fn add(self, other: LogicalMargin<T>) -> LogicalRect<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalRect {
start: LogicalPoint {
@ -927,9 +942,11 @@ impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for Logical
}
impl<T: Add<T, T> + Sub<T, T>> Sub<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> {
impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> Sub<LogicalMargin<T>> for LogicalRect<T> {
type Output = LogicalRect<T>;
#[inline]
fn sub(&self, other: &LogicalMargin<T>) -> LogicalRect<T> {
fn sub(self, other: LogicalMargin<T>) -> LogicalRect<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalRect {
start: LogicalPoint {
@ -950,7 +967,7 @@ impl<T: Add<T, T> + Sub<T, T>> Sub<LogicalMargin<T>, LogicalRect<T>> for Logical
}
#[cfg(test)]
fn modes() -> [WritingMode, ..10] {
fn modes() -> [WritingMode; 10] {
[
WritingMode::empty(),
FLAG_VERTICAL,

View file

@ -6,13 +6,16 @@
use libc::{c_char,c_int,c_void,size_t};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::io::timer::sleep;
#[cfg(target_os="linux")]
use std::io::File;
use std::mem;
use std::mem::size_of;
#[cfg(target_os="linux")]
use std::os::page_size;
use std::ptr::null_mut;
use std::sync::mpsc::{Sender, channel, Receiver};
use std::time::duration::Duration;
use task::spawn_named;
#[cfg(target_os="macos")]
@ -45,16 +48,16 @@ impl MemoryProfiler {
Some(period) => {
let period = Duration::milliseconds((period * 1000f64) as i64);
let chan = chan.clone();
spawn_named("Memory profiler timer".to_owned(), proc() {
spawn_named("Memory profiler timer".to_owned(), move || {
loop {
sleep(period);
if chan.send_opt(MemoryProfilerMsg::Print).is_err() {
if chan.send(MemoryProfilerMsg::Print).is_err() {
break;
}
}
});
// Spawn the memory profiler.
spawn_named("Memory profiler".to_owned(), proc() {
spawn_named("Memory profiler".to_owned(), move || {
let memory_profiler = MemoryProfiler::new(port);
memory_profiler.start();
});
@ -62,9 +65,9 @@ impl MemoryProfiler {
None => {
// No-op to handle messages when the memory profiler is
// inactive.
spawn_named("Memory profiler".to_owned(), proc() {
spawn_named("Memory profiler".to_owned(), move || {
loop {
match port.recv_opt() {
match port.recv() {
Err(_) | Ok(MemoryProfilerMsg::Exit) => break,
_ => {}
}
@ -84,7 +87,7 @@ impl MemoryProfiler {
pub fn start(&self) {
loop {
match self.port.recv_opt() {
match self.port.recv() {
Ok(msg) => {
if !self.handle_msg(msg) {
break
@ -151,12 +154,13 @@ extern {
fn get_jemalloc_stat(name: &'static str) -> Option<u64> {
let mut old: size_t = 0;
let c_name = name.to_c_str();
let c_name = CString::from_slice(name.as_bytes());
let oldp = &mut old as *mut _ as *mut c_void;
let mut oldlen = size_of::<size_t>() as size_t;
let rv: c_int;
unsafe {
rv = je_mallctl(c_name.into_inner(), oldp, &mut oldlen, null_mut(), 0);
rv = je_mallctl(c_name.as_ptr(), oldp, &mut oldlen, null_mut(), 0);
mem::forget(c_name); // XXX correct?
}
if rv == 0 { Some(old as u64) } else { None }
}
@ -164,7 +168,7 @@ fn get_jemalloc_stat(name: &'static str) -> Option<u64> {
// Like std::macros::try!, but for Option<>.
macro_rules! option_try(
($e:expr) => (match $e { Some(e) => e, None => return None })
)
);
#[cfg(target_os="linux")]
fn get_proc_self_statm_field(field: uint) -> Option<u64> {
@ -172,7 +176,7 @@ fn get_proc_self_statm_field(field: uint) -> Option<u64> {
match f.read_to_string() {
Ok(contents) => {
let s = option_try!(contents.as_slice().words().nth(field));
let npages: u64 = option_try!(from_str(s));
let npages: u64 = option_try!(s.parse());
Some(npages * (page_size() as u64))
}
Err(_) => None

View file

@ -20,7 +20,7 @@ use std::ptr;
use std::rt;
/// Global flags for Servo, currently set on the command line.
#[deriving(Clone)]
#[derive(Clone)]
pub struct Opts {
/// The initial URLs to load.
pub urls: Vec<String>,
@ -241,31 +241,31 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
};
let tile_size: uint = match opt_match.opt_str("s") {
Some(tile_size_str) => from_str(tile_size_str.as_slice()).unwrap(),
Some(tile_size_str) => tile_size_str.parse().unwrap(),
None => 512,
};
let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str|
ScaleFactor(from_str(dppx_str.as_slice()).unwrap())
ScaleFactor(dppx_str.parse().unwrap())
);
let mut n_paint_threads: uint = match opt_match.opt_str("t") {
Some(n_paint_threads_str) => from_str(n_paint_threads_str.as_slice()).unwrap(),
Some(n_paint_threads_str) => n_paint_threads_str.parse().unwrap(),
None => 1, // FIXME: Number of cores.
};
// If only the flag is present, default to a 5 second period for both profilers.
let time_profiler_period = opt_match.opt_default("p", "5").map(|period| {
from_str(period.as_slice()).unwrap()
period.parse().unwrap()
});
let memory_profiler_period = opt_match.opt_default("m", "5").map(|period| {
from_str(period.as_slice()).unwrap()
period.parse().unwrap()
});
let gpu_painting = !FORCE_CPU_PAINTING && opt_match.opt_present("g");
let mut layout_threads: uint = match opt_match.opt_str("y") {
Some(layout_threads_str) => from_str(layout_threads_str.as_slice()).unwrap(),
Some(layout_threads_str) => layout_threads_str.parse().unwrap(),
None => cmp::max(rt::default_sched_threads() * 3 / 4, 1),
};
@ -280,12 +280,12 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
}
let devtools_port = opt_match.opt_default("devtools", "6000").map(|port| {
from_str(port.as_slice()).unwrap()
port.parse().unwrap()
});
let initial_window_size = match opt_match.opt_str("resolution") {
Some(res_string) => {
let res: Vec<uint> = res_string.as_slice().split('x').map(|r| from_str(r).unwrap()).collect();
let res: Vec<uint> = res_string.split('x').map(|r| r.parse().unwrap()).collect();
TypedSize2D(res[0], res[1])
}
None => {

View file

@ -74,7 +74,9 @@ pub struct PersistentListIterator<'a,T> where T: 'a + Send + Sync {
entry: Option<&'a PersistentListEntry<T>>,
}
impl<'a,T> Iterator<&'a T> for PersistentListIterator<'a,T> where T: Send + Sync {
impl<'a,T> Iterator for PersistentListIterator<'a,T> where T: Send + Sync {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<&'a T> {
let entry = match self.entry {

View file

@ -26,7 +26,7 @@ impl RangeIndex<int> for int {
#[macro_export]
macro_rules! int_range_index {
($(#[$attr:meta])* struct $Self:ident($T:ty)) => (
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Show, Copy)]
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Show, Copy)]
$(#[$attr])*
pub struct $Self(pub $T);
@ -74,37 +74,39 @@ macro_rules! int_range_index {
}
}
impl Add<$Self, $Self> for $Self {
impl Add<$Self> for $Self {
type Output = $Self;
#[inline]
fn add(&self, other: &$Self) -> $Self {
fn add(self, other: $Self) -> $Self {
$Self(self.get() + other.get())
}
}
impl Sub<$Self, $Self> for $Self {
impl Sub<$Self> for $Self {
type Output = $Self;
#[inline]
fn sub(&self, other: &$Self) -> $Self {
fn sub(self, other: $Self) -> $Self {
$Self(self.get() - other.get())
}
}
impl Mul<$Self, $Self> for $Self {
impl Mul<$Self> for $Self {
type Output = $Self;
#[inline]
fn mul(&self, other: &$Self) -> $Self {
fn mul(self, other: $Self) -> $Self {
$Self(self.get() * other.get())
}
}
impl Neg<$Self> for $Self {
#[inline]
fn neg(&self) -> $Self {
$Self(-self.get())
}
}
impl Neg for $Self {
type Output = $Self;
impl ::std::num::One for $Self {
fn one() -> $Self {
$Self(1)
#[inline]
fn neg(self) -> $Self {
$Self(-self.get())
}
}
@ -124,66 +126,75 @@ macro_rules! int_range_index {
}
}
impl Div<$Self, $Self> for $Self {
fn div(&self, other: &$Self) -> $Self {
impl Div<$Self> for $Self {
type Output = $Self;
fn div(self, other: $Self) -> $Self {
$Self(self.get() / other.get())
}
}
impl Rem<$Self, $Self> for $Self {
fn rem(&self, other: &$Self) -> $Self {
impl Rem<$Self> for $Self {
type Output = $Self;
fn rem(self, other: $Self) -> $Self {
$Self(self.get() % other.get())
}
}
impl Not<$Self> for $Self {
fn not(&self) -> $Self {
impl Not for $Self {
type Output = $Self;
fn not(self) -> $Self {
$Self(!self.get())
}
}
impl BitAnd<$Self, $Self> for $Self {
fn bitand(&self, other: &$Self) -> $Self {
impl BitAnd<$Self> for $Self {
type Output = $Self;
fn bitand(self, other: $Self) -> $Self {
$Self(self.get() & other.get())
}
}
impl BitOr<$Self, $Self> for $Self {
fn bitor(&self, other: &$Self) -> $Self {
impl BitOr<$Self> for $Self {
type Output = $Self;
fn bitor(self, other: $Self) -> $Self {
$Self(self.get() | other.get())
}
}
impl BitXor<$Self, $Self> for $Self {
fn bitxor(&self, other: &$Self) -> $Self {
impl BitXor<$Self> for $Self {
type Output = $Self;
fn bitxor(self, other: $Self) -> $Self {
$Self(self.get() ^ other.get())
}
}
impl Shl<uint, $Self> for $Self {
fn shl(&self, n: &uint) -> $Self {
$Self(self.get() << *n)
impl Shl<uint> for $Self {
type Output = $Self;
fn shl(self, n: uint) -> $Self {
$Self(self.get() << n)
}
}
impl Shr<uint, $Self> for $Self {
fn shr(&self, n: &uint) -> $Self {
$Self(self.get() >> *n)
impl Shr<uint> for $Self {
type Output = $Self;
fn shr(self, n: uint) -> $Self {
$Self(self.get() >> n)
}
}
)
}
/// A range of indices
#[deriving(Clone, Encodable, Copy)]
#[derive(Clone, RustcEncodable, Copy)]
pub struct Range<I> {
begin: I,
length: I,
}
#[old_impl_check]
impl<I: RangeIndex<T>, T> fmt::Show for Range<I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{} .. {})", self.begin(), self.end())
write!(f, "[{:?} .. {:?})", self.begin(), self.end())
}
}
@ -196,7 +207,9 @@ pub fn each_index<T: Int, I: RangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I
EachIndex { it: iter::range(start.get(), stop.get()) }
}
impl<T: Int, I: RangeIndex<T>> Iterator<I> for EachIndex<T, I> {
impl<T: Int, I: RangeIndex<T>> Iterator for EachIndex<T, I> {
type Item = I;
#[inline]
fn next(&mut self) -> Option<I> {
self.it.next().map(|i| RangeIndex::new(i))
@ -208,6 +221,7 @@ impl<T: Int, I: RangeIndex<T>> Iterator<I> for EachIndex<T, I> {
}
}
#[old_impl_check]
impl<I: RangeIndex<T>, T> Range<I> {
/// Create a new range from beginning and length offsets. This could be
/// denoted as `[begin, begin + length)`.
@ -345,6 +359,7 @@ impl<I: RangeIndex<T>, T> Range<I> {
}
/// Methods for `Range`s with indices based on integer values
#[old_impl_check]
impl<T: Int, I: RangeIndex<T>> Range<I> {
/// Returns an iterater that increments over `[begin, end)`.
#[inline]
@ -363,8 +378,9 @@ impl<T: Int, I: RangeIndex<T>> Range<I> {
&& self.length() <= len
},
None => {
debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
max value for the range index (max={})", s_len,
debug!("Range<T>::is_valid_for_string: string length \
(len={:?}) is longer than the max value for the range \
index (max={:?})", s_len,
{
let max: T = Int::max_value();
let val: I = RangeIndex::new(max);

View file

@ -9,7 +9,8 @@ use std::mem::zeroed as i;
use std::cmp;
use std::fmt;
use std::intrinsics;
use std::kinds::marker::ContravariantLifetime;
use std::iter::FromIterator;
use std::marker::ContravariantLifetime;
use std::mem;
use std::ptr;
use std::raw::Slice;
@ -249,7 +250,9 @@ pub struct SmallVecIterator<'a,T> {
lifetime: ContravariantLifetime<'a>
}
impl<'a,T> Iterator<&'a T> for SmallVecIterator<'a,T> {
impl<'a,T> Iterator for SmallVecIterator<'a,T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<&'a T> {
unsafe {
@ -273,7 +276,9 @@ pub struct SmallVecMutIterator<'a,T> {
lifetime: ContravariantLifetime<'a>,
}
impl<'a,T> Iterator<&'a mut T> for SmallVecMutIterator<'a,T> {
impl<'a,T> Iterator for SmallVecMutIterator<'a,T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<&'a mut T> {
unsafe {
@ -298,7 +303,9 @@ pub struct SmallVecMoveIterator<'a,T> {
lifetime: ContravariantLifetime<'a>,
}
impl<'a, T: 'a> Iterator<T> for SmallVecMoveIterator<'a,T> {
impl<'a, T: 'a> Iterator for SmallVecMoveIterator<'a,T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
unsafe {
@ -341,7 +348,7 @@ macro_rules! def_small_vector(
len: uint,
cap: uint,
ptr: *const T,
data: [T, ..$size],
data: [T; $size],
}
impl<T> SmallVecPrivate<T> for $name<T> {
@ -403,7 +410,7 @@ macro_rules! def_small_vector(
}
impl<T> FromIterator<T> for $name<T> {
fn from_iter<I: Iterator<T>>(mut iter: I) -> $name<T> {
fn from_iter<I: Iterator<Item=T>>(mut iter: I) -> $name<T> {
let mut v = $name::new();
let (lower_size_bound, _) = iter.size_hint();
@ -421,7 +428,7 @@ macro_rules! def_small_vector(
}
impl<T> $name<T> {
pub fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
pub fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) {
let (lower_size_bound, _) = iter.size_hint();
let target_len = self.len() + lower_size_bound;
@ -438,7 +445,7 @@ macro_rules! def_small_vector(
impl<T: fmt::Show> fmt::Show for $name<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_slice())
write!(f, "{:?}", self.as_slice())
}
}
@ -456,15 +463,15 @@ macro_rules! def_small_vector(
}
}
)
)
);
def_small_vector!(SmallVec1, 1)
def_small_vector!(SmallVec2, 2)
def_small_vector!(SmallVec4, 4)
def_small_vector!(SmallVec8, 8)
def_small_vector!(SmallVec16, 16)
def_small_vector!(SmallVec24, 24)
def_small_vector!(SmallVec32, 32)
def_small_vector!(SmallVec1, 1);
def_small_vector!(SmallVec2, 2);
def_small_vector!(SmallVec4, 4);
def_small_vector!(SmallVec8, 8);
def_small_vector!(SmallVec16, 16);
def_small_vector!(SmallVec24, 24);
def_small_vector!(SmallVec32, 32);
macro_rules! def_small_vector_drop_impl(
($name:ident, $size:expr) => (
@ -488,15 +495,15 @@ macro_rules! def_small_vector_drop_impl(
}
}
)
)
);
def_small_vector_drop_impl!(SmallVec1, 1)
def_small_vector_drop_impl!(SmallVec2, 2)
def_small_vector_drop_impl!(SmallVec4, 4)
def_small_vector_drop_impl!(SmallVec8, 8)
def_small_vector_drop_impl!(SmallVec16, 16)
def_small_vector_drop_impl!(SmallVec24, 24)
def_small_vector_drop_impl!(SmallVec32, 32)
def_small_vector_drop_impl!(SmallVec1, 1);
def_small_vector_drop_impl!(SmallVec2, 2);
def_small_vector_drop_impl!(SmallVec4, 4);
def_small_vector_drop_impl!(SmallVec8, 8);
def_small_vector_drop_impl!(SmallVec16, 16);
def_small_vector_drop_impl!(SmallVec24, 24);
def_small_vector_drop_impl!(SmallVec32, 32);
macro_rules! def_small_vector_clone_impl(
($name:ident) => (
@ -510,15 +517,15 @@ macro_rules! def_small_vector_clone_impl(
}
}
)
)
);
def_small_vector_clone_impl!(SmallVec1)
def_small_vector_clone_impl!(SmallVec2)
def_small_vector_clone_impl!(SmallVec4)
def_small_vector_clone_impl!(SmallVec8)
def_small_vector_clone_impl!(SmallVec16)
def_small_vector_clone_impl!(SmallVec24)
def_small_vector_clone_impl!(SmallVec32)
def_small_vector_clone_impl!(SmallVec1);
def_small_vector_clone_impl!(SmallVec2);
def_small_vector_clone_impl!(SmallVec4);
def_small_vector_clone_impl!(SmallVec8);
def_small_vector_clone_impl!(SmallVec16);
def_small_vector_clone_impl!(SmallVec24);
def_small_vector_clone_impl!(SmallVec32);
#[cfg(test)]
pub mod tests {

View file

@ -81,6 +81,7 @@ pub fn quicksort_by<T>(arr: &mut [T], compare: fn(&T, &T) -> Ordering) {
#[cfg(test)]
pub mod test {
use std::cmp::Ordering;
use std::rand;
use std::rand::Rng;
@ -88,7 +89,7 @@ pub mod test {
#[test]
pub fn random() {
let mut rng = rand::task_rng();
let mut rng = rand::thread_rng();
for _ in range(0u32, 50000u32) {
let len: uint = rng.gen();
let mut v: Vec<int> = rng.gen_iter::<int>().take((len % 32) + 1).collect();

View file

@ -5,12 +5,14 @@
use geometry::Au;
use cssparser::{mod, RGBA, Color};
use libc::c_char;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::ffi::c_str_to_bytes;
use std::iter::Filter;
use std::num::Int;
use std::str::{CharEq, CharSplits, FromStr};
use unicode::char::UnicodeChar;
use std::num::{Int, ToPrimitive};
use std::str::{from_utf8, CharEq, FromStr, Split};
pub type DOMString = String;
pub type StaticCharVec = &'static [char];
@ -65,15 +67,16 @@ pub static HTML_SPACE_CHARACTERS: StaticCharVec = &[
'\u{000d}',
];
pub fn split_html_space_chars<'a>(s: &'a str)
-> Filter<'a, &'a str, CharSplits<'a, StaticCharVec>> {
s.split(HTML_SPACE_CHARACTERS).filter(|&split| !split.is_empty())
pub fn split_html_space_chars<'a>(s: &'a str) ->
Filter<&'a str, Split<'a, StaticCharVec>, fn(&&str) -> bool> {
fn not_empty(&split: &&str) -> bool { !split.is_empty() }
s.split(HTML_SPACE_CHARACTERS).filter(not_empty as fn(&&str) -> bool)
}
/// Shared implementation to parse an integer according to
/// <http://www.whatwg.org/html/#rules-for-parsing-integers> or
/// <http://www.whatwg.org/html/#rules-for-parsing-non-negative-integers>.
fn do_parse_integer<T: Iterator<char>>(input: T) -> Option<i64> {
fn do_parse_integer<T: Iterator<Item=char>>(input: T) -> Option<i64> {
fn is_ascii_digit(c: &char) -> bool {
match *c {
'0'...'9' => true,
@ -118,7 +121,7 @@ fn do_parse_integer<T: Iterator<char>>(input: T) -> Option<i64> {
/// Parse an integer according to
/// <http://www.whatwg.org/html/#rules-for-parsing-integers>.
pub fn parse_integer<T: Iterator<char>>(input: T) -> Option<i32> {
pub fn parse_integer<T: Iterator<Item=char>>(input: T) -> Option<i32> {
do_parse_integer(input).and_then(|result| {
result.to_i32()
})
@ -126,13 +129,13 @@ pub fn parse_integer<T: Iterator<char>>(input: T) -> Option<i32> {
/// Parse an integer according to
/// <http://www.whatwg.org/html/#rules-for-parsing-non-negative-integers>.
pub fn parse_unsigned_integer<T: Iterator<char>>(input: T) -> Option<u32> {
pub fn parse_unsigned_integer<T: Iterator<Item=char>>(input: T) -> Option<u32> {
do_parse_integer(input).and_then(|result| {
result.to_u32()
})
}
#[deriving(Copy)]
#[derive(Copy)]
pub enum LengthOrPercentageOrAuto {
Auto,
Percentage(f64),
@ -141,14 +144,14 @@ pub enum LengthOrPercentageOrAuto {
/// Parses a length per HTML5 § 2.4.4.4. If unparseable, `Auto` is returned.
pub fn parse_length(mut value: &str) -> LengthOrPercentageOrAuto {
value = value.trim_left_chars(Whitespace);
value = value.trim_left_matches(Whitespace);
if value.len() == 0 {
return LengthOrPercentageOrAuto::Auto
}
if value.starts_with("+") {
value = value.slice_from(1)
}
value = value.trim_left_chars('0');
value = value.trim_left_matches('0');
if value.len() == 0 {
return LengthOrPercentageOrAuto::Auto
}
@ -197,7 +200,7 @@ pub fn parse_legacy_color(mut input: &str) -> Result<RGBA,()> {
}
// Step 3.
input = input.trim_left_chars(Whitespace).trim_right_chars(Whitespace);
input = input.trim_left_matches(Whitespace).trim_right_matches(Whitespace);
// Step 4.
if input.eq_ignore_ascii_case("transparent") {
@ -321,7 +324,7 @@ pub fn parse_legacy_color(mut input: &str) -> Result<RGBA,()> {
}
#[deriving(Clone, Eq, PartialEq, Hash, Show)]
#[derive(Clone, Eq, PartialEq, Hash, Show)]
pub struct LowercaseString {
inner: String,
}
@ -340,3 +343,9 @@ impl Str for LowercaseString {
self.inner.as_slice()
}
}
/// Creates a String from the given null-terminated buffer.
/// Panics if the buffer does not contain UTF-8.
pub unsafe fn c_str_to_string(s: *const c_char) -> String {
from_utf8(c_str_to_bytes(&s)).unwrap().to_owned()
}

View file

@ -3,33 +3,37 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::borrow::ToOwned;
use std::task;
use std::comm::Sender;
use std::task::TaskBuilder;
use task_state;
use std::thread;
use std::sync::mpsc::Sender;
use std::thread::Builder;
pub fn spawn_named(name: String, f: proc():Send) {
let builder = task::TaskBuilder::new().named(name);
builder.spawn(proc() {
f();
pub fn spawn_named<F>(name: String, f: F)
where F: FnOnce() + Send
{
let builder = thread::Builder::new().name(name);
builder.spawn(move || {
f()
});
}
/// Arrange to send a particular message to a channel if the task fails.
pub fn spawn_named_with_send_on_failure<T: Send>(name: &'static str,
state: task_state::TaskState,
f: proc(): Send,
msg: T,
dest: Sender<T>) {
let future_result = TaskBuilder::new().named(name).try_future(proc() {
pub fn spawn_named_with_send_on_failure<F, T>(name: &'static str,
state: task_state::TaskState,
f: F,
msg: T,
dest: Sender<T>)
where F: FnOnce() + Send,
T: Send
{
let future_handle = thread::Builder::new().name(name.to_owned()).scoped(move || {
task_state::initialize(state);
f();
f()
});
let watched_name = name.to_owned();
let watcher_name = format!("{}Watcher", watched_name);
TaskBuilder::new().named(watcher_name).spawn(proc() {
match future_result.into_inner() {
let watcher_name = format!("{}Watcher", name);
Builder::new().name(watcher_name).spawn(move || {
match future_handle.join() {
Ok(()) => (),
Err(..) => {
debug!("{} failed, notifying constellation", name);
@ -38,3 +42,10 @@ pub fn spawn_named_with_send_on_failure<T: Send>(name: &'static str,
}
});
}
#[test]
fn spawn_named_test() {
spawn_named("Test".to_owned(), move || {
debug!("I can run!");
});
}

View file

@ -11,7 +11,7 @@
pub use self::imp::{initialize, get, enter, exit};
bitflags! {
#[deriving(Show, Copy)]
#[derive(Show)]
flags TaskState: u32 {
const SCRIPT = 0x01,
const LAYOUT = 0x02,
@ -35,7 +35,7 @@ macro_rules! task_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
#[cfg(not(ndebug))]
static TYPES: &'static [TaskState]
= &[ $( $flag ),* ];
))
));
task_types! {
is_script = SCRIPT;
@ -48,12 +48,12 @@ mod imp {
use super::{TaskState, TYPES};
use std::cell::RefCell;
thread_local!(static STATE: RefCell<Option<TaskState>> = RefCell::new(None))
thread_local!(static STATE: RefCell<Option<TaskState>> = RefCell::new(None));
pub fn initialize(x: TaskState) {
STATE.with(|ref k| {
match *k.borrow() {
Some(s) => panic!("Task state already initialized as {}", s),
Some(s) => panic!("Task state already initialized as {:?}", s),
None => ()
};
*k.borrow_mut() = Some(x);

View file

@ -17,9 +17,11 @@
use task::spawn_named;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thunk::Thunk;
pub struct TaskPool {
tx: Sender<proc():Send>,
tx: Sender<Thunk<()>>,
}
impl TaskPool {
@ -33,23 +35,25 @@ impl TaskPool {
let state = state.clone();
spawn_named(
format!("TaskPoolWorker {}/{}", i+1, tasks),
proc() worker(&*state));
move || worker(&*state));
}
return TaskPool { tx: tx };
fn worker(rx: &Mutex<Receiver<proc():Send>>) {
fn worker(rx: &Mutex<Receiver<Thunk<()>>>) {
loop {
let job = rx.lock().recv_opt();
let job = rx.lock().unwrap().recv();
match job {
Ok(job) => job(),
Ok(job) => job.invoke(()),
Err(..) => break,
}
}
}
}
pub fn execute(&self, job: proc():Send) {
self.tx.send(job);
pub fn execute<F>(&self, job: F)
where F: FnOnce() + Send
{
self.tx.send(Thunk::new(job));
}
}

View file

@ -2,13 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Ordering};
use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
use std::rc::Rc;
use std::cell::RefCell;
static mut next_tid: AtomicUint = INIT_ATOMIC_UINT;
static mut next_tid: AtomicUint = ATOMIC_UINT_INIT;
thread_local!(static TASK_LOCAL_TID: Rc<RefCell<Option<uint>>> = Rc::new(RefCell::new(None)))
thread_local!(static TASK_LOCAL_TID: Rc<RefCell<Option<uint>>> = Rc::new(RefCell::new(None)));
/// Every task gets one, that's unique.
pub fn tid() -> uint {

View file

@ -4,21 +4,21 @@
//! Timing functions.
use collections::TreeMap;
use collections::BTreeMap;
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::comm::{Sender, channel, Receiver};
use std::f64;
use std::io::timer::sleep;
use std::iter::AdditiveIterator;
use std::num::FloatMath;
use std::num::Float;
use std::sync::mpsc::{Sender, channel, Receiver};
use std::time::duration::Duration;
use std_time::precise_time_ns;
use task::{spawn_named};
use url::Url;
// front-end representation of the profiler used to communicate with the profiler
#[deriving(Clone)]
#[derive(Clone)]
pub struct TimeProfilerChan(pub Sender<TimeProfilerMsg>);
impl TimeProfilerChan {
@ -28,7 +28,7 @@ impl TimeProfilerChan {
}
}
#[deriving(PartialEq, Clone, PartialOrd, Eq, Ord)]
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)]
pub struct TimerMetadata {
url: String,
iframe: bool,
@ -60,7 +60,7 @@ impl Formatable for Option<TimerMetadata> {
}
}
#[deriving(Clone)]
#[derive(Clone)]
pub enum TimeProfilerMsg {
/// Normal message used for reporting time
Time((TimeProfilerCategory, Option<TimerMetadata>), f64),
@ -71,7 +71,7 @@ pub enum TimeProfilerMsg {
}
#[repr(u32)]
#[deriving(PartialEq, Clone, PartialOrd, Eq, Ord)]
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)]
pub enum TimeProfilerCategory {
Compositing,
LayoutPerform,
@ -130,7 +130,7 @@ impl Formatable for TimeProfilerCategory {
}
}
type TimeProfilerBuckets = TreeMap<(TimeProfilerCategory, Option<TimerMetadata>), Vec<f64>>;
type TimeProfilerBuckets = BTreeMap<(TimeProfilerCategory, Option<TimerMetadata>), Vec<f64>>;
// back end of the profiler that handles data aggregation and performance metrics
pub struct TimeProfiler {
@ -146,25 +146,25 @@ impl TimeProfiler {
Some(period) => {
let period = Duration::milliseconds((period * 1000f64) as i64);
let chan = chan.clone();
spawn_named("Time profiler timer".to_owned(), proc() {
spawn_named("Time profiler timer".to_owned(), move || {
loop {
sleep(period);
if chan.send_opt(TimeProfilerMsg::Print).is_err() {
if chan.send(TimeProfilerMsg::Print).is_err() {
break;
}
}
});
// Spawn the time profiler.
spawn_named("Time profiler".to_owned(), proc() {
spawn_named("Time profiler".to_owned(), move || {
let mut profiler = TimeProfiler::new(port);
profiler.start();
});
}
None => {
// No-op to handle messages when the time profiler is inactive.
spawn_named("Time profiler".to_owned(), proc() {
spawn_named("Time profiler".to_owned(), move || {
loop {
match port.recv_opt() {
match port.recv() {
Err(_) | Ok(TimeProfilerMsg::Exit) => break,
_ => {}
}
@ -179,14 +179,14 @@ impl TimeProfiler {
pub fn new(port: Receiver<TimeProfilerMsg>) -> TimeProfiler {
TimeProfiler {
port: port,
buckets: TreeMap::new(),
buckets: BTreeMap::new(),
last_msg: None,
}
}
pub fn start(&mut self) {
loop {
let msg = self.port.recv_opt();
let msg = self.port.recv();
match msg {
Ok(msg) => {
if !self.handle_msg(msg) {
@ -249,13 +249,13 @@ impl TimeProfiler {
}
}
#[deriving(Eq, PartialEq)]
#[derive(Eq, PartialEq)]
pub enum TimerMetadataFrameType {
RootWindow,
IFrame,
}
#[deriving(Eq, PartialEq)]
#[derive(Eq, PartialEq)]
pub enum TimerMetadataReflowType {
Incremental,
FirstReflow,
@ -263,11 +263,13 @@ pub enum TimerMetadataReflowType {
pub type ProfilerMetadata<'a> = Option<(&'a Url, TimerMetadataFrameType, TimerMetadataReflowType)>;
pub fn profile<T>(category: TimeProfilerCategory,
meta: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
callback: || -> T)
-> T {
pub fn profile<T, F>(category: TimeProfilerCategory,
meta: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
callback: F)
-> T
where F: FnOnce() -> T
{
let start_time = precise_time_ns();
let val = callback();
let end_time = precise_time_ns();
@ -282,7 +284,9 @@ pub fn profile<T>(category: TimeProfilerCategory,
return val;
}
pub fn time<T>(msg: &str, callback: || -> T) -> T{
pub fn time<T, F>(msg: &str, callback: F) -> T
where F: Fn() -> T
{
let start_time = precise_time_ns();
let val = callback();
let end_time = precise_time_ns();

View file

@ -78,7 +78,7 @@ fn test_miss_all_elems<T: PartialEq + PartialOrd + Eq + Ord + Show>(arr: &[T], m
let mut i = 0;
while i < misses.len() {
let res = arr.binary_search_(&misses[i]);
debug!("{} == {} ?", misses[i], res);
debug!("{:?} == {:?} ?", misses[i], res);
assert!(!test_match(&misses[i], arr.binary_search_(&misses[i])));
i += 1;
}

View file

@ -15,6 +15,7 @@ use rand::{Rng, XorShiftRng};
use std::mem;
use std::rand::weak_rng;
use std::sync::atomic::{AtomicUint, Ordering};
use std::sync::mpsc::{channel, Sender, Receiver};
use deque::{Abort, BufferPool, Data, Empty, Stealer, Worker};
/// A unit of work.
@ -31,7 +32,7 @@ pub struct WorkUnit<QueueData, WorkData> {
}
/// Messages from the supervisor to the worker.
enum WorkerMsg<QueueData, WorkData> {
enum WorkerMsg<QueueData: 'static, WorkData: 'static> {
/// Tells the worker to start work.
Start(Worker<WorkUnit<QueueData, WorkData>>, *mut AtomicUint, *const QueueData),
/// Tells the worker to stop. It can be restarted again with a `WorkerMsg::Start`.
@ -40,14 +41,18 @@ enum WorkerMsg<QueueData, WorkData> {
Exit,
}
unsafe impl<QueueData: 'static, WorkData: 'static> Send for WorkerMsg<QueueData, WorkData> {}
/// Messages to the supervisor.
enum SupervisorMsg<QueueData, WorkData> {
enum SupervisorMsg<QueueData: 'static, WorkData: 'static> {
Finished,
ReturnDeque(uint, Worker<WorkUnit<QueueData, WorkData>>),
}
unsafe impl<QueueData: 'static, WorkData: 'static> Send for SupervisorMsg<QueueData, WorkData> {}
/// Information that the supervisor thread keeps about the worker threads.
struct WorkerInfo<QueueData, WorkData> {
struct WorkerInfo<QueueData: 'static, WorkData: 'static> {
/// The communication channel to the workers.
chan: Sender<WorkerMsg<QueueData, WorkData>>,
/// The worker end of the deque, if we have it.
@ -57,7 +62,7 @@ struct WorkerInfo<QueueData, WorkData> {
}
/// Information specific to each worker thread that the thread keeps.
struct WorkerThread<QueueData, WorkData> {
struct WorkerThread<QueueData: 'static, WorkData: 'static> {
/// The index of this worker.
index: uint,
/// The communication port from the supervisor.
@ -70,6 +75,8 @@ struct WorkerThread<QueueData, WorkData> {
rng: XorShiftRng,
}
unsafe impl<QueueData: 'static, WorkData: 'static> Send for WorkerThread<QueueData, WorkData> {}
static SPIN_COUNT: u32 = 128;
static SPINS_UNTIL_BACKOFF: u32 = 100;
static BACKOFF_INCREMENT_IN_US: u32 = 5;
@ -80,7 +87,7 @@ impl<QueueData: Send, WorkData: Send> WorkerThread<QueueData, WorkData> {
fn start(&mut self) {
loop {
// Wait for a start message.
let (mut deque, ref_count, queue_data) = match self.port.recv() {
let (mut deque, ref_count, queue_data) = match self.port.recv().unwrap() {
WorkerMsg::Start(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
WorkerMsg::Stop => panic!("unexpected stop message"),
WorkerMsg::Exit => return,
@ -158,13 +165,13 @@ impl<QueueData: Send, WorkData: Send> WorkerThread<QueueData, WorkData> {
// the last work unit in the queue, then send a message on the channel.
unsafe {
if (*ref_count).fetch_sub(1, Ordering::SeqCst) == 1 {
self.chan.send(SupervisorMsg::Finished)
self.chan.send(SupervisorMsg::Finished).unwrap()
}
}
}
// Give the deque back to the supervisor.
self.chan.send(SupervisorMsg::ReturnDeque(self.index, deque))
self.chan.send(SupervisorMsg::ReturnDeque(self.index, deque)).unwrap()
}
}
}
@ -196,7 +203,7 @@ impl<'a, QueueData: 'static, WorkData: Send> WorkerProxy<'a, QueueData, WorkData
}
/// A work queue on which units of work can be submitted.
pub struct WorkQueue<QueueData, WorkData> {
pub struct WorkQueue<QueueData: 'static, WorkData: 'static> {
/// Information about each of the workers.
workers: Vec<WorkerInfo<QueueData, WorkData>>,
/// A port on which deques can be received from the workers.
@ -250,7 +257,7 @@ impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
spawn_named(
format!("{} worker {}/{}", task_name, i+1, thread_count),
proc() {
move || {
task_state::initialize(state | task_state::IN_WORKER);
let mut thread = thread;
thread.start()
@ -283,7 +290,7 @@ impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
// Tell the workers to start.
let mut work_count = AtomicUint::new(self.work_count);
for worker in self.workers.iter_mut() {
worker.chan.send(WorkerMsg::Start(worker.deque.take().unwrap(), &mut work_count, &self.data))
worker.chan.send(WorkerMsg::Start(worker.deque.take().unwrap(), &mut work_count, &self.data)).unwrap()
}
// Wait for the work to finish.
@ -292,12 +299,12 @@ impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
// Tell everyone to stop.
for worker in self.workers.iter() {
worker.chan.send(WorkerMsg::Stop)
worker.chan.send(WorkerMsg::Stop).unwrap()
}
// Get our deques back.
for _ in range(0, self.workers.len()) {
match self.port.recv() {
match self.port.recv().unwrap() {
SupervisorMsg::ReturnDeque(index, deque) => self.workers[index].deque = Some(deque),
SupervisorMsg::Finished => panic!("unexpected finished message!"),
}
@ -306,7 +313,7 @@ impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
pub fn shutdown(&mut self) {
for worker in self.workers.iter() {
worker.chan.send(WorkerMsg::Exit)
worker.chan.send(WorkerMsg::Exit).unwrap()
}
}
}