diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2014-03-12 22:01:33 +0200 |
|---|---|---|
| committer | Eduard Burtescu <edy.burt@gmail.com> | 2014-03-12 22:01:33 +0200 |
| commit | 500bade87e48eacf5cf14e236ca46bd434e542d6 (patch) | |
| tree | 3c1a1c60706a33a06e3fd0517d2e3aa271b3aa63 | |
| parent | 397abb7242b7d2d3e14a3a11b1ec8b5dadeea06f (diff) | |
| download | rust-500bade87e48eacf5cf14e236ca46bd434e542d6.tar.gz rust-500bade87e48eacf5cf14e236ca46bd434e542d6.zip | |
Vec: remove the drop flag to make it no larger than (*T, uint, uint).
| -rw-r--r-- | src/libstd/vec_ng.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index 76fd68a5265..f324f62f36b 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -32,6 +32,7 @@ use raw::Slice; use vec::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector}; use vec::{RevItems}; +#[unsafe_no_drop_flag] pub struct Vec<T> { priv len: uint, priv cap: uint, @@ -565,6 +566,8 @@ pub fn append_one<T>(mut lhs: Vec<T>, x: T) -> Vec<T> { #[unsafe_destructor] impl<T> Drop for Vec<T> { fn drop(&mut self) { + // This is (and should always remain) a no-op if the fields are + // zeroed (when moving out, because of #[unsafe_no_drop_flag]). unsafe { for x in self.as_mut_slice().iter() { ptr::read(x); @@ -629,7 +632,54 @@ impl<T> Drop for MoveItems<T> { mod tests { use super::Vec; use iter::{Iterator, range, Extendable}; + use mem::{drop, size_of}; + use ops::Drop; use option::{Some, None}; + use ptr; + + #[test] + fn test_small_vec_struct() { + assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3); + } + + #[test] + fn test_double_drop() { + struct TwoVec<T> { + x: Vec<T>, + y: Vec<T> + } + + struct DropCounter<'a> { + count: &'a mut int + } + + #[unsafe_destructor] + impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } + } + + let mut count_x @ mut count_y = 0; + { + let mut tv = TwoVec { + x: Vec::new(), + y: Vec::new() + }; + tv.x.push(DropCounter {count: &mut count_x}); + tv.y.push(DropCounter {count: &mut count_y}); + + // If Vec had a drop flag, here is where it would be zeroed. + // Instead, it should rely on its internal state to prevent + // doing anything significant when dropped multiple times. + drop(tv.x); + + // Here tv goes out of scope, tv.y should be dropped, but not tv.x. + } + + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); + } #[test] fn test_reserve_additional() { |
