Skip to content

Commit 3e97b7f

Browse files
committed
---
yaml --- r: 140508 b: refs/heads/try2 c: 393a409 h: refs/heads/master v: v3
1 parent 0d2daa1 commit 3e97b7f

File tree

11 files changed

+258
-449
lines changed

11 files changed

+258
-449
lines changed

[refs]

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

branches/try2/src/libcore/container.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ pub trait Map<K, V>: Mutable {
5555
/// Remove a key-value pair from the map. Return true if the key
5656
/// was present in the map, otherwise false.
5757
fn remove(&mut self, key: &K) -> bool;
58+
59+
/// Insert a key-value pair from the map. If the key already had a value
60+
/// present in the map, that value is returned. Otherwise None is returned.
61+
fn swap(&mut self, k: K, v: V) -> Option<V>;
62+
63+
/// Removes a key from the map, returning the value at the key if the key
64+
/// was previously in the map.
65+
fn pop(&mut self, k: &K) -> Option<V>;
5866
}
5967

6068
pub trait Set<T>: Mutable {

branches/try2/src/libcore/hashmap.rs

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use rand::RngUtil;
2424
use rand;
2525
use uint;
2626
use vec;
27-
use util::unreachable;
2827
use kinds::Copy;
28+
use util::{replace, unreachable};
2929

3030
static INITIAL_CAPACITY: uint = 32u; // 2^5
3131

@@ -204,7 +204,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
204204
/// Inserts the key value pair into the buckets.
205205
/// Assumes that there will be a bucket.
206206
/// True if there was no previous entry with that key
207-
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> bool {
207+
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> Option<V> {
208208
match self.bucket_for_key_with_hash(hash, &k) {
209209
TableFull => { fail!(~"Internal logic error"); }
210210
FoundHole(idx) => {
@@ -213,14 +213,19 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
213213
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
214214
value: v});
215215
self.size += 1;
216-
true
216+
None
217217
}
218218
FoundEntry(idx) => {
219219
debug!("insert overwrite (%?->%?) at idx %?, hash %?",
220220
k, v, idx, hash);
221-
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
222-
value: v});
223-
false
221+
match self.buckets[idx] {
222+
None => { fail!(~"insert_internal: Internal logic error") }
223+
Some(ref mut b) => {
224+
b.hash = hash;
225+
b.key = k;
226+
Some(replace(&mut b.value, v))
227+
}
228+
}
224229
}
225230
}
226231
}
@@ -361,6 +366,20 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
361366
/// key is replaced by the new value. Return true if the key did
362367
/// not already exist in the map.
363368
fn insert(&mut self, k: K, v: V) -> bool {
369+
self.swap(k, v).is_none()
370+
}
371+
372+
/// Remove a key-value pair from the map. Return true if the key
373+
/// was present in the map, otherwise false.
374+
fn remove(&mut self, k: &K) -> bool {
375+
self.pop(k).is_some()
376+
}
377+
378+
/// Insert a key-value pair from the map. If the key already had a value
379+
/// present in the map, that value is returned. Otherwise None is returned.
380+
fn swap(&mut self, k: K, v: V) -> Option<V> {
381+
// this could be faster.
382+
364383
if self.size >= self.resize_at {
365384
// n.b.: We could also do this after searching, so
366385
// that we do not resize if this call to insert is
@@ -375,10 +394,11 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
375394
self.insert_internal(hash, k, v)
376395
}
377396
378-
/// Remove a key-value pair from the map. Return true if the key
379-
/// was present in the map, otherwise false.
380-
fn remove(&mut self, k: &K) -> bool {
381-
self.pop(k).is_some()
397+
/// Removes a key from the map, returning the value at the key if the key
398+
/// was previously in the map.
399+
fn pop(&mut self, k: &K) -> Option<V> {
400+
let hash = k.hash_keyed(self.k0, self.k1) as uint;
401+
self.pop_internal(hash, k)
382402
}
383403
}
384404
@@ -402,31 +422,6 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
402422
}
403423
}
404424
405-
fn pop(&mut self, k: &K) -> Option<V> {
406-
let hash = k.hash_keyed(self.k0, self.k1) as uint;
407-
self.pop_internal(hash, k)
408-
}
409-
410-
fn swap(&mut self, k: K, v: V) -> Option<V> {
411-
// this could be faster.
412-
let hash = k.hash_keyed(self.k0, self.k1) as uint;
413-
let old_value = self.pop_internal(hash, &k);
414-
415-
if self.size >= self.resize_at {
416-
// n.b.: We could also do this after searching, so
417-
// that we do not resize if this call to insert is
418-
// simply going to update a key in place. My sense
419-
// though is that it's worse to have to search through
420-
// buckets to find the right spot twice than to just
421-
// resize in this corner case.
422-
self.expand();
423-
}
424-
425-
self.insert_internal(hash, k, v);
426-
427-
old_value
428-
}
429-
430425
/// Return the value corresponding to the key in the map, or insert
431426
/// and return the value if it doesn't exist.
432427
fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V {

branches/try2/src/libcore/run.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,4 +855,74 @@ mod tests {
855855
fn waitpid_non_existant_pid() {
856856
run::waitpid(123456789); // assume that this pid doesn't exist
857857
}
858+
859+
#[test]
860+
fn test_destroy_once() {
861+
let mut p = run::start_program("echo", []);
862+
p.destroy(); // this shouldn't crash (and nor should the destructor)
863+
}
864+
865+
#[test]
866+
fn test_destroy_twice() {
867+
let mut p = run::start_program("echo", []);
868+
p.destroy(); // this shouldnt crash...
869+
p.destroy(); // ...and nor should this (and nor should the destructor)
870+
}
871+
872+
fn test_destroy_actually_kills(force: bool) {
873+
874+
#[cfg(unix)]
875+
static BLOCK_COMMAND: &'static str = "cat";
876+
877+
#[cfg(windows)]
878+
static BLOCK_COMMAND: &'static str = "cmd";
879+
880+
#[cfg(unix)]
881+
fn process_exists(pid: libc::pid_t) -> bool {
882+
run::program_output("ps", [~"-p", pid.to_str()]).out.contains(pid.to_str())
883+
}
884+
885+
#[cfg(windows)]
886+
fn process_exists(pid: libc::pid_t) -> bool {
887+
888+
use libc::types::os::arch::extra::DWORD;
889+
use libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess};
890+
use libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE };
891+
892+
unsafe {
893+
let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
894+
if proc.is_null() {
895+
return false;
896+
}
897+
// proc will be non-null if the process is alive, or if it died recently
898+
let mut status = 0;
899+
GetExitCodeProcess(proc, &mut status);
900+
CloseHandle(proc);
901+
return status == STILL_ACTIVE;
902+
}
903+
}
904+
905+
// this program will stay alive indefinitely trying to read from stdin
906+
let mut p = run::start_program(BLOCK_COMMAND, []);
907+
908+
assert!(process_exists(p.get_id()));
909+
910+
if force {
911+
p.force_destroy();
912+
} else {
913+
p.destroy();
914+
}
915+
916+
assert!(!process_exists(p.get_id()));
917+
}
918+
919+
#[test]
920+
fn test_unforced_destroy_actually_kills() {
921+
test_destroy_actually_kills(false);
922+
}
923+
924+
#[test]
925+
fn test_forced_destroy_actually_kills() {
926+
test_destroy_actually_kills(true);
927+
}
858928
}

branches/try2/src/libcore/trie.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! An ordered map and set for integer keys implemented as a radix trie
1212
1313
use prelude::*;
14+
use util::{swap, replace};
1415

1516
// FIXME: #5244: need to manually update the TrieNode constructor
1617
static SHIFT: uint = 4;
@@ -110,21 +111,33 @@ impl<T> Map<uint, T> for TrieMap<T> {
110111
/// not already exist in the map.
111112
#[inline(always)]
112113
fn insert(&mut self, key: uint, value: T) -> bool {
113-
let ret = insert(&mut self.root.count,
114-
&mut self.root.children[chunk(key, 0)],
115-
key, value, 1);
116-
if ret { self.length += 1 }
117-
ret
114+
self.swap(key, value).is_none()
118115
}
119116

120117
/// Remove a key-value pair from the map. Return true if the key
121118
/// was present in the map, otherwise false.
122119
#[inline(always)]
123120
fn remove(&mut self, key: &uint) -> bool {
121+
self.pop(key).is_some()
122+
}
123+
124+
/// Insert a key-value pair from the map. If the key already had a value
125+
/// present in the map, that value is returned. Otherwise None is returned.
126+
fn swap(&mut self, key: uint, value: T) -> Option<T> {
127+
let ret = insert(&mut self.root.count,
128+
&mut self.root.children[chunk(key, 0)],
129+
key, value, 1);
130+
if ret.is_none() { self.length += 1 }
131+
ret
132+
}
133+
134+
/// Removes a key from the map, returning the value at the key if the key
135+
/// was previously in the map.
136+
fn pop(&mut self, key: &uint) -> Option<T> {
124137
let ret = remove(&mut self.root.count,
125138
&mut self.root.children[chunk(*key, 0)],
126139
*key, 1);
127-
if ret { self.length -= 1 }
140+
if ret.is_some() { self.length -= 1 }
128141
ret
129142
}
130143
}
@@ -289,61 +302,65 @@ fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint)
289302
}
290303

291304
fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
292-
idx: uint) -> bool {
305+
idx: uint) -> Option<T> {
293306
let mut tmp = Nothing;
294-
tmp <-> *child;
295-
let mut added = false;
307+
let ret;
308+
swap(&mut tmp, child);
296309

297310
*child = match tmp {
298311
External(stored_key, stored_value) => {
299312
if stored_key == key {
313+
ret = Some(stored_value);
300314
External(stored_key, value)
301315
} else {
302316
// conflict - split the node
303317
let mut new = ~TrieNode::new();
304318
insert(&mut new.count,
305319
&mut new.children[chunk(stored_key, idx)],
306320
stored_key, stored_value, idx + 1);
307-
insert(&mut new.count, &mut new.children[chunk(key, idx)], key,
308-
value, idx + 1);
309-
added = true;
321+
ret = insert(&mut new.count, &mut new.children[chunk(key, idx)],
322+
key, value, idx + 1);
310323
Internal(new)
311324
}
312325
}
313326
Internal(x) => {
314327
let mut x = x;
315-
added = insert(&mut x.count, &mut x.children[chunk(key, idx)], key,
316-
value, idx + 1);
328+
ret = insert(&mut x.count, &mut x.children[chunk(key, idx)], key,
329+
value, idx + 1);
317330
Internal(x)
318331
}
319332
Nothing => {
320333
*count += 1;
321-
added = true;
334+
ret = None;
322335
External(key, value)
323336
}
324337
};
325-
added
338+
return ret;
326339
}
327340

328341
fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
329-
idx: uint) -> bool {
342+
idx: uint) -> Option<T> {
330343
let (ret, this) = match *child {
331-
External(stored, _) => {
332-
if stored == key { (true, true) } else { (false, false) }
344+
External(stored, _) if stored == key => {
345+
match replace(child, Nothing) {
346+
External(_, value) => (Some(value), true),
347+
_ => fail!()
348+
}
333349
}
350+
External(*) => (None, false),
334351
Internal(ref mut x) => {
335352
let ret = remove(&mut x.count, &mut x.children[chunk(key, idx)],
336353
key, idx + 1);
337354
(ret, x.count == 0)
338355
}
339-
Nothing => (false, false)
356+
Nothing => (None, false)
340357
};
341358

342359
if this {
343360
*child = Nothing;
344361
*count -= 1;
345362
}
346-
ret
363+
return ret;
347364
}
348365

349366
#[cfg(test)]
@@ -516,4 +533,20 @@ mod tests {
516533
i += 1;
517534
}
518535
}
536+
537+
#[test]
538+
fn test_swap() {
539+
let mut m = TrieMap::new();
540+
assert!(m.swap(1, 2) == None);
541+
assert!(m.swap(1, 3) == Some(2));
542+
assert!(m.swap(1, 4) == Some(3));
543+
}
544+
545+
#[test]
546+
fn test_pop() {
547+
let mut m = TrieMap::new();
548+
m.insert(1, 2);
549+
assert!(m.pop(&1) == Some(2));
550+
assert!(m.pop(&1) == None);
551+
}
519552
}

0 commit comments

Comments
 (0)