mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Update rustc to 00b112c45a604fa6f4b59af2a40c9deeadfdb7c6/rustc-1.0.0-dev.
This commit is contained in:
parent
ff8cbff810
commit
95fc29fa0d
255 changed files with 3550 additions and 3362 deletions
|
@ -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 = "*"
|
|
@ -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;
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 doesn’t 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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue