Skip to content

Commit

Permalink
core: changes in response to rust-lang#5656
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Apr 11, 2013
1 parent 49de82c commit 61b9e0e
Show file tree
Hide file tree
Showing 12 changed files with 700 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/libcore/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct Condition<'self, T, U> {
}

pub impl<'self, T, U> Condition<'self, T, U> {
fn trap(&self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
unsafe {
let p : *RustClosure = ::cast::transmute(&h);
let prev = task::local_data::local_data_get(self.key);
Expand Down
36 changes: 36 additions & 0 deletions src/libcore/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub trait Mutable: Container {
fn clear(&mut self);
}

#[cfg(stage0)]
pub trait Map<K, V>: Mutable {
/// Return true if the map contains a value for the specified key
fn contains_key(&self, key: &K) -> bool;
Expand Down Expand Up @@ -57,6 +58,41 @@ pub trait Map<K, V>: Mutable {
fn remove(&mut self, key: &K) -> bool;
}

#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
pub trait Map<K, V>: Mutable {
/// Return true if the map contains a value for the specified key
fn contains_key(&self, key: &K) -> bool;

// Visits all keys and values
fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool);

/// Visit all keys
fn each_key(&self, f: &fn(&K) -> bool);

/// Visit all values
fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool);

/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool);

/// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, key: &K) -> Option<&'a V>;

/// Return a mutable reference to the value corresponding to the key
fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>;

/// Insert a key-value pair into the map. An existing value for a
/// key is replaced by the new value. Return true if the key did
/// not already exist in the map.
fn insert(&mut self, key: K, value: V) -> bool;

/// Remove a key-value pair from the map. Return true if the key
/// was present in the map, otherwise false.
fn remove(&mut self, key: &K) -> bool;
}

pub trait Set<T>: Mutable {
/// Return true if the set contains a value
fn contains(&self, value: &T) -> bool;
Expand Down
173 changes: 171 additions & 2 deletions src/libcore/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
}
}

#[cfg(stage0)]
#[inline(always)]
fn value_for_bucket(&self, idx: uint) -> &'self V {
match self.buckets[idx] {
Expand All @@ -194,6 +195,18 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
}
}

#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
#[inline(always)]
fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V {
match self.buckets[idx] {
Some(ref bkt) => &bkt.value,
None => fail!(~"HashMap::find: internal logic error"),
}
}

#[cfg(stage0)]
#[inline(always)]
fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V {
match self.buckets[idx] {
Expand All @@ -202,6 +215,17 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
}
}

#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
#[inline(always)]
fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V {
match self.buckets[idx] {
Some(ref mut bkt) => &mut bkt.value,
None => unreachable()
}
}

/// Inserts the key value pair into the buckets.
/// Assumes that there will be a bucket.
/// True if there was no previous entry with that key
Expand Down Expand Up @@ -307,6 +331,7 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
}

/// Visit all key-value pairs
#[cfg(stage0)]
fn each(&self, blk: &fn(&'self K, &'self V) -> bool) {
for uint::range(0, self.buckets.len()) |i| {
for self.buckets[i].each |bucket| {
Expand All @@ -317,19 +342,41 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
}
}

/// Visit all key-value pairs
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn each<'a>(&'a self, blk: &fn(&'a K, &'a V) -> bool) {
for uint::range(0, self.buckets.len()) |i| {
for self.buckets[i].each |bucket| {
if !blk(&bucket.key, &bucket.value) {
return;
}
}
}
}

/// Visit all keys
fn each_key(&self, blk: &fn(k: &K) -> bool) {
self.each(|k, _| blk(k))
}

/// Visit all values
#[cfg(stage0)]
fn each_value(&self, blk: &fn(v: &V) -> bool) {
self.each(|_, v| blk(v))
}

/// Visit all values
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) {
self.each(|_, v| blk(v))
}

/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, blk: &fn(&'self K,
&'self mut V) -> bool) {
fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) {
for uint::range(0, self.buckets.len()) |i| {
match self.buckets[i] {
Some(Bucket{key: ref key, value: ref mut value, _}) => {
Expand All @@ -341,14 +388,27 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
}

/// Return a reference to the value corresponding to the key
#[cfg(stage0)]
fn find(&self, k: &K) -> Option<&'self V> {
match self.bucket_for_key(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
}
}

/// Return a reference to the value corresponding to the key
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
match self.bucket_for_key(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
}
}

/// Return a mutable reference to the value corresponding to the key
#[cfg(stage0)]
fn find_mut(&mut self, k: &K) -> Option<&'self mut V> {
let idx = match self.bucket_for_key(k) {
FoundEntry(idx) => idx,
Expand All @@ -359,6 +419,20 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
}
}

/// Return a mutable reference to the value corresponding to the key
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
let idx = match self.bucket_for_key(k) {
FoundEntry(idx) => idx,
TableFull | FoundHole(_) => return None
};
unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker
Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx)))
}
}

/// Insert a key-value pair into the map. An existing value for a
/// key is replaced by the new value. Return true if the key did
/// not already exist in the map.
Expand Down Expand Up @@ -431,6 +505,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {

/// Return the value corresponding to the key in the map, or insert
/// and return the value if it doesn't exist.
#[cfg(stage0)]
fn find_or_insert(&mut self, k: K, v: V) -> &'self V {
if self.size >= self.resize_at {
// n.b.: We could also do this after searching, so
Expand Down Expand Up @@ -459,8 +534,42 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
}
}

/// Return the value corresponding to the key in the map, or insert
/// and return the value if it doesn't exist.
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V {
if self.size >= self.resize_at {
// n.b.: We could also do this after searching, so
// that we do not resize if this call to insert is
// simply going to update a key in place. My sense
// though is that it's worse to have to search through
// buckets to find the right spot twice than to just
// resize in this corner case.
self.expand();
}

let hash = k.hash_keyed(self.k0, self.k1) as uint;
let idx = match self.bucket_for_key_with_hash(hash, &k) {
TableFull => fail!(~"Internal logic error"),
FoundEntry(idx) => idx,
FoundHole(idx) => {
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
value: v});
self.size += 1;
idx
},
};

unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker
::cast::transmute_region(self.value_for_bucket(idx))
}
}

/// Return the value corresponding to the key in the map, or create,
/// insert, and return a new value if it doesn't exist.
#[cfg(stage0)]
fn find_or_insert_with(&mut self, k: K, f: &fn(&K) -> V) -> &'self V {
if self.size >= self.resize_at {
// n.b.: We could also do this after searching, so
Expand Down Expand Up @@ -490,6 +599,40 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
}
}

/// Return the value corresponding to the key in the map, or create,
/// insert, and return a new value if it doesn't exist.
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V {
if self.size >= self.resize_at {
// n.b.: We could also do this after searching, so
// that we do not resize if this call to insert is
// simply going to update a key in place. My sense
// though is that it's worse to have to search through
// buckets to find the right spot twice than to just
// resize in this corner case.
self.expand();
}

let hash = k.hash_keyed(self.k0, self.k1) as uint;
let idx = match self.bucket_for_key_with_hash(hash, &k) {
TableFull => fail!(~"Internal logic error"),
FoundEntry(idx) => idx,
FoundHole(idx) => {
let v = f(&k);
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
value: v});
self.size += 1;
idx
},
};

unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker
::cast::transmute_region(self.value_for_bucket(idx))
}
}

fn consume(&mut self, f: &fn(K, V)) {
let mut buckets = ~[];
self.buckets <-> buckets;
Expand All @@ -506,13 +649,24 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
}
}

#[cfg(stage0)]
fn get(&self, k: &K) -> &'self V {
match self.find(k) {
Some(v) => v,
None => fail!(fmt!("No entry found for key: %?", k)),
}
}

#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn get<'a>(&'a self, k: &K) -> &'a V {
match self.find(k) {
Some(v) => v,
None => fail!(fmt!("No entry found for key: %?", k)),
}
}

/// Return true if the map contains a value for the specified key,
/// using equivalence
fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, key: &Q)
Expand All @@ -525,13 +679,28 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {

/// Return the value corresponding to the key in the map, using
/// equivalence
#[cfg(stage0)]
fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q)
-> Option<&'self V> {
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
}
}

/// Return the value corresponding to the key in the map, using
/// equivalence
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find_equiv<'a, Q:Hash + IterBytes + Equiv<K>>(
&'a self, k: &Q) -> Option<&'a V>
{
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
}
}
}

impl<K:Hash + IterBytes + Eq,V:Eq> Eq for HashMap<K, V> {
Expand Down
Loading

1 comment on commit 61b9e0e

@pcwalton
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

Please sign in to comment.