diff options
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/core.rc | 11 | ||||
| -rw-r--r-- | src/libcore/dvec.rs | 355 | ||||
| -rw-r--r-- | src/libcore/io.rs | 42 | ||||
| -rw-r--r-- | src/libcore/iter-trait/dvec.rs | 37 | ||||
| -rw-r--r-- | src/libcore/prelude.rs | 1 | ||||
| -rw-r--r-- | src/libcore/repr.rs | 13 | ||||
| -rw-r--r-- | src/libcore/task/local_data_priv.rs | 25 |
7 files changed, 41 insertions, 443 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 21d83618684..79a5d297178 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -21,10 +21,10 @@ used features. the floating point types, the `bool` type, tuples, characters, strings, vectors (`vec`), managed boxes (`managed`), owned boxes (`owned`), and unsafe and borrowed pointers (`ptr`). Additionally, `core` provides task management -and creation (`task`), communication primitives (`comm` and `pipes`), an -efficient vector builder (`dvec`), platform abstractions (`os` and `path`), -basic I/O abstractions (`io`), common traits (`cmp`, `num`, `to_str`), and -complete bindings to the C standard library (`libc`). +and creation (`task`), communication primitives (`comm` and `pipes`), platform +abstractions (`os` and `path`), basic I/O abstractions (`io`), common traits +(`cmp`, `num`, `to_str`), and complete bindings to the C standard library +(`libc`). `core` is linked to all crates by default and its contents imported. Implicitly, all crates behave as if they included the following prologue: @@ -141,9 +141,6 @@ pub mod container; pub mod option; pub mod result; pub mod either; -pub mod dvec; -#[path="iter-trait.rs"] #[merge = "iter-trait/dvec.rs"] -pub mod dvec_iter; pub mod dlist; #[path="iter-trait.rs"] #[merge = "iter-trait/dlist.rs"] pub mod dlist_iter; diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs deleted file mode 100644 index 43daf5fa6a5..00000000000 --- a/src/libcore/dvec.rs +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Dynamic vector - -A growable vector that makes use of unique pointers so that the -result can be sent between tasks and so forth. - -Note that recursive use is not permitted. - -*/ - -use cast; -use prelude::*; -use ptr::null; -use vec; - -/** - * A growable, modifiable vector type that accumulates elements into a - * unique vector. - * - * # Limitations on recursive use - * - * This class works by swapping the unique vector out of the data - * structure whenever it is to be used. Therefore, recursive use is not - * permitted. That is, while iterating through a vector, you cannot - * access the vector in any other way or else the program will fail. If - * you wish, you can use the `swap()` method to gain access to the raw - * vector and transform it or use it any way you like. Eventually, we - * may permit read-only access during iteration or other use. - * - * # WARNING - * - * For maximum performance, this type is implemented using some rather - * unsafe code. In particular, this innocent looking `~[mut A]` pointer - * *may be null!* Therefore, it is important you not reach into the - * data structure manually but instead use the provided extensions. - * - * The reason that I did not use an unsafe pointer in the structure - * itself is that I wanted to ensure that the vector would be freed when - * the dvec is dropped. The reason that I did not use an `Option<T>` - * instead of a nullable pointer is that I found experimentally that it - * becomes approximately 50% slower. This can probably be improved - * through optimization. You can run your own experiments using - * `src/test/bench/vec-append.rs`. My own tests found that using null - * pointers achieved about 103 million pushes/second. Using an option - * type could only produce 47 million pushes/second. - */ -pub struct DVec<A> { - mut data: ~[A] -} - -/// Creates a new, empty dvec -pub pure fn DVec<A>() -> DVec<A> { - DVec {data: ~[]} -} - -/// Creates a new dvec with a single element -pub pure fn from_elem<A>(e: A) -> DVec<A> { - DVec {data: ~[e]} -} - -/// Creates a new dvec with the contents of a vector -pub pure fn from_vec<A>(v: ~[A]) -> DVec<A> { - DVec {data: v} -} - -/// Consumes the vector and returns its contents -pub pure fn unwrap<A>(d: DVec<A>) -> ~[A] { - let DVec {data: v} = d; - v -} - -priv impl<A> DVec<A> { - #[inline(always)] - pure fn check_not_borrowed(&self) { - unsafe { - let data: *() = cast::reinterpret_cast(&self.data); - if data.is_null() { - fail!(~"Recursive use of dvec"); - } - } - } - - #[inline(always)] - fn give_back(&self, data: ~[A]) { - unsafe { - self.data = data; - } - } - - #[inline(always)] - fn unwrap(self) -> ~[A] { unwrap(self) } -} - -// In theory, most everything should work with any A, but in practice -// almost nothing works without the copy bound due to limitations -// around closures. -pub impl<A> DVec<A> { - // FIXME (#3758): This should not need to be public. - #[inline(always)] - fn check_out<B>(&self, f: &fn(v: ~[A]) -> B) -> B { - unsafe { - let mut data = cast::reinterpret_cast(&null::<()>()); - data <-> self.data; - let data_ptr: *() = cast::reinterpret_cast(&data); - if data_ptr.is_null() { fail!(~"Recursive use of dvec"); } - return f(data); - } - } - - /// Reserves space for N elements - fn reserve(&self, count: uint) { - vec::reserve(&mut self.data, count) - } - - /** - * Swaps out the current vector and hands it off to a user-provided - * function `f`. The function should transform it however is desired - * and return a new vector to replace it with. - */ - #[inline(always)] - fn swap(&self, f: &fn(v: ~[A]) -> ~[A]) { - self.check_out(|v| self.give_back(f(v))) - } - - /// Returns the number of elements currently in the dvec - #[inline(always)] - pure fn len(&self) -> uint { - self.check_not_borrowed(); - return self.data.len(); - } - - /// Overwrite the current contents - #[inline(always)] - fn set(&self, w: ~[A]) { - self.check_not_borrowed(); - self.data = w; - } - - /// Remove and return the last element - fn pop(&self) -> A { - do self.check_out |v| { - let mut v = v; - let result = v.pop(); - self.give_back(v); - result - } - } - - /// Insert a single item at the front of the list - fn unshift(&self, t: A) { - unsafe { - let mut data = cast::reinterpret_cast(&null::<()>()); - data <-> self.data; - let data_ptr: *() = cast::reinterpret_cast(&data); - if data_ptr.is_null() { fail!(~"Recursive use of dvec"); } - self.data = ~[t]; - self.data.push_all_move(data); - } - } - - /// Append a single item to the end of the list - #[inline(always)] - fn push(&self, t: A) { - self.check_not_borrowed(); - self.data.push(t); - } - - /// Remove and return the first element - fn shift(&self) -> A { - do self.check_out |v| { - let mut v = v; - let result = v.shift(); - self.give_back(v); - result - } - } - - /// Reverse the elements in the list, in place - fn reverse(&self) { - do self.check_out |v| { - let mut v = v; - vec::reverse(v); - self.give_back(v); - } - } - - /// Gives access to the vector as a slice with immutable contents - fn borrow<R>(&self, op: fn(x: &[A]) -> R) -> R { - do self.check_out |v| { - let result = op(v); - self.give_back(v); - result - } - } - - /// Gives access to the vector as a slice with mutable contents - fn borrow_mut<R>(&self, op: &fn(x: &mut [A]) -> R) -> R { - do self.check_out |v| { - let mut v = v; - let result = op(v); - self.give_back(v); - result - } - } -} - -pub impl<A:Copy> DVec<A> { - /** - * Append all elements of a vector to the end of the list - * - * Equivalent to `append_iter()` but potentially more efficient. - */ - fn push_all(&self, ts: &[const A]) { - self.push_slice(ts, 0u, vec::len(ts)); - } - - /// Appends elements from `from_idx` to `to_idx` (exclusive) - fn push_slice(&self, ts: &[const A], from_idx: uint, to_idx: uint) { - do self.swap |v| { - let mut v = v; - let new_len = vec::len(v) + to_idx - from_idx; - vec::reserve(&mut v, new_len); - let mut i = from_idx; - while i < to_idx { - v.push(ts[i]); - i += 1u; - } - v - } - } - - /** - * Append all elements of an iterable. - * - * Failure will occur if the iterable's `each()` method - * attempts to access this vector. - */ - /* - fn append_iter<A, I:iter::base_iter<A>>(ts: I) { - do self.swap |v| { - let mut v = match ts.size_hint() { - none { v } - Some(h) { - let len = v.len() + h; - let mut v = v; - vec::reserve(v, len); - v - } - }; - - for ts.each |t| { v.push(*t) }; - v - } - } - */ - - /** - * Gets a copy of the current contents. - * - * See `unwrap()` if you do not wish to copy the contents. - */ - pure fn get(&self) -> ~[A] { - unsafe { - do self.check_out |v| { - let w = copy v; - self.give_back(v); - w - } - } - } - - /// Copy out an individual element - #[inline(always)] - pure fn get_elt(&self, idx: uint) -> A { - self.check_not_borrowed(); - return self.data[idx]; - } - - /// Overwrites the contents of the element at `idx` with `a` - fn set_elt(&self, idx: uint, a: A) { - self.check_not_borrowed(); - self.data[idx] = a; - } - - /** - * Overwrites the contents of the element at `idx` with `a`, - * growing the vector if necessary. New elements will be initialized - * with `initval` - */ - fn grow_set_elt(&self, idx: uint, initval: &A, val: A) { - do self.swap |v| { - let mut v = v; - v.grow_set(idx, initval, val); - v - } - } - - /// Returns the last element, failing if the vector is empty - #[inline(always)] - pure fn last(&self) -> A { - self.check_not_borrowed(); - - let length = self.len(); - if length == 0 { - fail!(~"attempt to retrieve the last element of an empty vector"); - } - - return self.data[length - 1]; - } - - /// Iterates over the elements in reverse order - #[inline(always)] - fn rev_each(&self, f: fn(v: &A) -> bool) { - do self.swap |v| { - // FIXME(#2263)---we should be able to write - // `vec::rev_each(v, f);` but we cannot write now - for vec::rev_each(v) |e| { - if !f(e) { break; } - } - v - } - } - - /// Iterates over the elements and indices in reverse order - #[inline(always)] - fn rev_eachi(&self, f: fn(uint, v: &A) -> bool) { - do self.swap |v| { - // FIXME(#2263)---we should be able to write - // `vec::rev_eachi(v, f);` but we cannot write now - for vec::rev_eachi(v) |i, e| { - if !f(i, e) { break; } - } - v - } - } -} - -impl<A:Copy> Index<uint,A> for DVec<A> { - #[inline(always)] - pure fn index(&self, idx: uint) -> A { - self.get_elt(idx) - } -} - diff --git a/src/libcore/io.rs b/src/libcore/io.rs index cc40b90d61a..4634eb8793d 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -16,7 +16,6 @@ Basic input/output use result::Result; -use dvec::DVec; use int; use libc; use libc::{c_int, c_long, c_uint, c_void, size_t, ssize_t}; @@ -1109,30 +1108,25 @@ pub fn print(s: &str) { stdout().write_str(s); } pub fn println(s: &str) { stdout().write_line(s); } pub struct BytesWriter { - bytes: DVec<u8>, + mut bytes: ~[u8], mut pos: uint, } impl Writer for BytesWriter { fn write(&self, v: &[const u8]) { - do self.bytes.swap |bytes| { - let mut bytes = bytes; - let v_len = v.len(); - let bytes_len = bytes.len(); - - let count = uint::max(bytes_len, self.pos + v_len); - vec::reserve(&mut bytes, count); - unsafe { vec::raw::set_len(&mut bytes, count); } - - { - let view = vec::mut_slice(bytes, self.pos, count); - vec::bytes::copy_memory(view, v, v_len); - } + let v_len = v.len(); + let bytes_len = self.bytes.len(); - self.pos += v_len; + let count = uint::max(bytes_len, self.pos + v_len); + vec::reserve(&mut self.bytes, count); - bytes + unsafe { + vec::raw::set_len(&mut self.bytes, count); + let view = vec::mut_slice(self.bytes, self.pos, count); + vec::bytes::copy_memory(view, v, v_len); } + + self.pos += v_len; } fn seek(&self, offset: int, whence: SeekStyle) { let pos = self.pos; @@ -1145,14 +1139,14 @@ impl Writer for BytesWriter { } pub pure fn BytesWriter() -> BytesWriter { - BytesWriter { bytes: DVec(), mut pos: 0u } + BytesWriter { bytes: ~[], mut pos: 0u } } pub pure fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { let wr = @BytesWriter(); f(wr as Writer); - // FIXME (#3758): This should not be needed. - unsafe { wr.bytes.check_out(|bytes| bytes) } + let @BytesWriter{bytes, _} = wr; + return bytes; } pub pure fn with_str_writer(f: fn(Writer)) -> ~str { @@ -1448,17 +1442,15 @@ mod tests { fn bytes_buffer_overwrite() { let wr = BytesWriter(); wr.write(~[0u8, 1u8, 2u8, 3u8]); - fail_unless!(wr.bytes.borrow(|bytes| bytes == ~[0u8, 1u8, 2u8, 3u8])); + fail_unless!(wr.bytes == ~[0u8, 1u8, 2u8, 3u8]); wr.seek(-2, SeekCur); wr.write(~[4u8, 5u8, 6u8, 7u8]); - fail_unless!(wr.bytes.borrow(|bytes| bytes == - ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8])); + fail_unless!(wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); wr.seek(-2, SeekEnd); wr.write(~[8u8]); wr.seek(1, SeekSet); wr.write(~[9u8]); - fail_unless!(wr.bytes.borrow(|bytes| bytes == - ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8])); + fail_unless!(wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); } #[test] diff --git a/src/libcore/iter-trait/dvec.rs b/src/libcore/iter-trait/dvec.rs deleted file mode 100644 index 986aa18ad4a..00000000000 --- a/src/libcore/iter-trait/dvec.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod inst { - use dvec; - use option::{Option, Some}; - - #[allow(non_camel_case_types)] - pub type IMPL_T<A> = dvec::DVec<A>; - - /** - * Iterates through the current contents. - * - * Attempts to access this dvec during iteration will fail. - */ - #[inline(always)] - pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) { - unsafe { - do self.swap |v| { - v.each(f); - v - } - } - } - - #[inline(always)] - pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> { - Some(self.len()) - } -} diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index e4be0cf98dd..2f575ce7d28 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -50,7 +50,6 @@ pub use bool; pub use cast; pub use char; pub use cmp; -pub use dvec; pub use either; pub use f32; pub use f64; diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index eaae9d03e8e..e9122754eb4 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -16,7 +16,6 @@ More runtime type reflection use cast::transmute; use char; -use dvec::DVec; use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use io::{Writer, WriterUtil}; @@ -147,14 +146,14 @@ enum VariantState { pub struct ReprVisitor { mut ptr: *c_void, - ptr_stk: DVec<*c_void>, - var_stk: DVec<VariantState>, + mut ptr_stk: ~[*c_void], + mut var_stk: ~[VariantState], writer: @Writer } pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { ReprVisitor { ptr: ptr, - ptr_stk: DVec(), - var_stk: DVec(), + ptr_stk: ~[], + var_stk: ~[], writer: writer } } @@ -500,7 +499,7 @@ impl TyVisitor for ReprVisitor { } fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { - match self.var_stk.last() { + match self.var_stk[self.var_stk.len() - 1] { Degenerate | TagMatch => { if i != 0 { self.writer.write_str(", "); @@ -518,7 +517,7 @@ impl TyVisitor for ReprVisitor { _disr_val: int, n_fields: uint, _name: &str) -> bool { - match self.var_stk.last() { + match self.var_stk[self.var_stk.len() - 1] { Degenerate | TagMatch => { if n_fields > 0 { self.writer.write_char(')'); diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index cb1283019eb..f035916f594 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -12,7 +12,6 @@ use cast; use cmp::Eq; -use dvec; use libc; use option; use prelude::*; @@ -35,11 +34,11 @@ impl Eq for LocalData { pure fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) } } -// We use dvec because it's the best data structure in core. If TLS is used -// heavily in future, this could be made more efficient with a proper map. +// If TLS is used heavily in future, this could be made more efficient with a +// proper map. type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData); // Has to be a pointer at outermost layer; the foreign call returns void *. -type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>; +type TaskLocalMap = @mut ~[Option<TaskLocalElement>]; extern fn cleanup_task_local_map(map_ptr: *libc::c_void) { unsafe { @@ -60,17 +59,21 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap { // drop when they finish. No "re-storing after modifying" is needed. let map_ptr = rt::rust_get_task_local_data(task); if map_ptr.is_null() { - let map: TaskLocalMap = @dvec::DVec(); + let map: TaskLocalMap = @mut ~[]; // Use reinterpret_cast -- transmute would take map away from us also. rt::rust_set_task_local_data( task, cast::reinterpret_cast(&map)); rt::rust_task_local_data_atexit(task, cleanup_task_local_map); // Also need to reference it an extra time to keep it for now. - cast::bump_box_refcount(map); + let nonmut = cast::transmute::<TaskLocalMap, + @~[Option<TaskLocalElement>]>(map); + cast::bump_box_refcount(nonmut); map } else { let map = cast::transmute(map_ptr); - cast::bump_box_refcount(map); + let nonmut = cast::transmute::<TaskLocalMap, + @~[Option<TaskLocalElement>]>(map); + cast::bump_box_refcount(nonmut); map } } @@ -118,7 +121,7 @@ unsafe fn local_get_helper<T:Durable>( let data: @T = cast::transmute(data_ptr); cast::bump_box_refcount(data); if do_pop { - (*map).set_elt(index, None); + map[index] = None; } data } @@ -159,13 +162,13 @@ pub unsafe fn local_set<T:Durable>( Some((index, _old_data_ptr)) => { // Key already had a value set, _old_data_ptr, whose reference // will get dropped when the local_data box is overwritten. - (*map).set_elt(index, new_entry); + map[index] = new_entry; } None => { // Find an empty slot. If not, grow the vector. match (*map).position(|x| x.is_none()) { - Some(empty_index) => (*map).set_elt(empty_index, new_entry), - None => (*map).push(new_entry) + Some(empty_index) => { map[empty_index] = new_entry; } + None => { map.push(new_entry); } } } } |
