1
+ // Dynamic Vector
2
+ //
3
+ // A growable vector that makes use of unique pointers so that the
4
+ // result can be sent between tasks and so forth.
5
+ //
6
+ // Note that recursive use is not permitted.
7
+
8
+ import dvec_iter:: extensions;
9
+ import unsafe:: reinterpret_cast;
10
+ import ptr :: { null, extensions} ;
11
+
12
+ export dvec;
13
+ export from_vec;
14
+ export extensions;
15
+ export unwrap;
16
+
17
+ #[ doc = "
18
+
19
+ A growable, modifiable vector type that accumulates elements into a
20
+ unique vector.
21
+
22
+ # Limitations on recursive use
23
+
24
+ This class works by swapping the unique vector out of the data
25
+ structure whenever it is to be used. Therefore, recursive use is not
26
+ permitted. That is, while iterating through a vector, you cannot
27
+ access the vector in any other way or else the program will fail. If
28
+ you wish, you can use the `swap()` method to gain access to the raw
29
+ vector and transform it or use it any way you like. Eventually, we
30
+ may permit read-only access during iteration or other use.
31
+
32
+ # WARNING
33
+
34
+ For maximum performance, this type is implemented using some rather
35
+ unsafe code. In particular, this innocent looking `[mut A]` pointer
36
+ *may be null!* Therefore, it is important you not reach into the
37
+ data structure manually but instead use the provided extensions.
38
+
39
+ The reason that I did not use an unsafe pointer in the structure
40
+ itself is that I wanted to ensure that the vector would be freed when
41
+ the dvec is dropped. The reason that I did not use an `option<T>`
42
+ instead of a nullable pointer is that I found experimentally that it
43
+ becomes approximately 50% slower. This can probably be improved
44
+ through optimization. You can run your own experiments using
45
+ `src/test/bench/vec-append.rs`. My own tests found that using null
46
+ pointers achieved about 103 million pushes/second. Using an option
47
+ type could only produce 47 million pushes/second.
48
+
49
+ " ]
50
+ type dvec < A > = {
51
+
52
+ mut data : [ mut A ]
53
+ } ;
54
+
55
+ #[ doc = "Creates a new, empty dvec" ]
56
+ fn dvec < A > ( ) -> dvec < A > {
57
+ { mut data: [ mut] }
58
+ }
59
+
60
+ #[ doc = "Creates a new dvec with the contents of a vector" ]
61
+ fn from_vec < A > ( +v : [ mut A ] ) -> dvec < A > {
62
+ { mut data: v}
63
+ }
64
+
65
+ #[ doc = "Consumes the vector and returns its contents" ]
66
+ fn unwrap < A > ( -d : dvec < A > ) -> [ mut A ] {
67
+ let { data: v } <- d;
68
+ ret v;
69
+ }
70
+
71
+ impl private_methods < A > for dvec < A > {
72
+ fn check_not_borrowed ( ) {
73
+ unsafe {
74
+ let data: * ( ) = unsafe :: reinterpret_cast ( self . data ) ;
75
+ if data. is_null ( ) {
76
+ fail "Recursive use of dvec" ;
77
+ }
78
+ }
79
+ }
80
+
81
+ #[ inline( always) ]
82
+ fn borrow < B > ( f : fn ( -[ mut A ] ) -> B ) -> B {
83
+ unsafe {
84
+ let mut data = unsafe :: reinterpret_cast ( null :: < ( ) > ( ) ) ;
85
+ data <-> self . data ;
86
+ let data_ptr: * ( ) = unsafe :: reinterpret_cast ( data) ;
87
+ if data_ptr. is_null ( ) { fail "Recursive use of dvec" ; }
88
+ ret f( data) ;
89
+ }
90
+ }
91
+
92
+ #[ inline( always) ]
93
+ fn return ( -data : [ mut A ] ) {
94
+ unsafe {
95
+ self . data <- data;
96
+ }
97
+ }
98
+ }
99
+
100
+ // In theory, most everything should work with any A, but in practice
101
+ // almost nothing works without the copy bound due to limitations
102
+ // around closures.
103
+ impl extensions < A > for dvec < A > {
104
+ #[ doc = "
105
+
106
+ Swaps out the current vector and hands it off to a user-provided
107
+ function `f`. The function should transform it however is desired
108
+ and return a new vector to replace it with.
109
+
110
+ " ]
111
+ fn swap ( f : fn ( -[ mut A ] ) -> [ mut A ] ) {
112
+ self . borrow { |v| self . return ( f ( v) ) }
113
+ }
114
+
115
+ #[ doc = "Returns the number of elements currently in the dvec" ]
116
+ fn len ( ) -> uint {
117
+ self . borrow { |v|
118
+ let l = v. len ( ) ;
119
+ self . return ( v) ;
120
+ l
121
+ }
122
+ }
123
+
124
+ #[ doc = "Overwrite the current contents" ]
125
+ fn set ( +w : [ mut A ] ) {
126
+ self . check_not_borrowed ( ) ;
127
+ self . data <- w; //FIXME check for recursive use
128
+ }
129
+ }
130
+
131
+ impl extensions < A : copy > for dvec < A > {
132
+ #[ doc = "Append a single item to the end of the list" ]
133
+ fn push ( t : A ) {
134
+ self . swap { |v| v += [ t] ; v } // more efficient than v + [t]
135
+ }
136
+
137
+ #[ doc = "Remove and return the last element" ]
138
+ fn pop ( ) -> A {
139
+ self . borrow { |v|
140
+ let result = vec:: pop ( v) ;
141
+ self . return ( v) ;
142
+ result
143
+ }
144
+ }
145
+
146
+ #[ doc = "
147
+ Append all elements of a vector to the end of the list
148
+
149
+ Equivalent to `append_iter()` but potentially more efficient.
150
+ " ]
151
+ fn push_all ( ts : [ const A ] /& ) {
152
+ self . push_slice ( ts, 0 u, vec:: len ( ts) ) ;
153
+ }
154
+
155
+ #[ doc = "
156
+ Appends elements from `from_idx` to `to_idx` (exclusive)
157
+ " ]
158
+ fn push_slice ( ts : [ const A ] /& , from_idx : uint , to_idx : uint ) {
159
+ self . swap { |v|
160
+ let new_len = vec:: len ( v) + to_idx - from_idx;
161
+ vec:: reserve ( v, new_len) ;
162
+ let mut i = from_idx;
163
+ while i < to_idx {
164
+ v += [ ts[ i] ] ;
165
+ i += 1 u;
166
+ }
167
+ v
168
+ }
169
+ }
170
+
171
+ //FIXME--
172
+ //#[doc = "
173
+ // Append all elements of an iterable.
174
+ //
175
+ // Failure will occur if the iterable's `each()` method
176
+ // attempts to access this vector.
177
+ //"]
178
+ //fn append_iter<I:iter::base<A>>(ts: I) {
179
+ // self.dvec.swap { |v|
180
+ // alt ts.size_hint() {
181
+ // none {}
182
+ // some(h) { vec::reserve(v, len(v) + h) }
183
+ // }
184
+ //
185
+ // for ts.each { |t| v = v + [t] };
186
+ //
187
+ // v
188
+ // }
189
+ //}
190
+
191
+ #[ doc = "
192
+ Gets a copy of the current contents.
193
+
194
+ See `unwrap()` if you do not wish to copy the contents.
195
+ " ]
196
+ fn get ( ) -> [ A ] {
197
+ self . borrow { |v|
198
+ let w = vec:: from_mut ( copy v) ;
199
+ self . return ( v) ;
200
+ w
201
+ }
202
+ }
203
+
204
+ #[ doc = "Remove and return the first element" ]
205
+ fn shift ( ) -> A {
206
+ self . borrow { |v|
207
+ let mut v = vec:: from_mut ( v) ;
208
+ let result = vec:: shift ( v) ;
209
+ self . return ( vec:: to_mut ( v) ) ;
210
+ result
211
+ }
212
+ }
213
+
214
+ #[ doc = "Copy out an individual element" ]
215
+ #[ inline]
216
+ fn [ ] ( idx: uint) -> A {
217
+ self. get_elt ( idx)
218
+ }
219
+
220
+ #[ doc = "Copy out an individual element" ]
221
+ #[ inline]
222
+ fn get_elt ( idx : uint ) -> A {
223
+ self . check_not_borrowed ( ) ;
224
+ ret self. data [ idx] ;
225
+ }
226
+
227
+ #[ doc = "Overwrites the contents of the element at `idx` with `a`" ]
228
+ fn set_elt ( idx : uint , a : A ) {
229
+ self . check_not_borrowed ( ) ;
230
+ self . data [ idx] = a;
231
+ }
232
+
233
+ #[ doc = "Overwrites the contents of the element at `idx` with `a`" ]
234
+ fn grow_set_elt ( idx : uint , initval : A , val : A ) {
235
+ self . swap { |v| vec:: grow_set ( v, idx, initval, val) ; v }
236
+ }
237
+ }
0 commit comments