1+ use std:: alloc:: { self , Layout } ;
2+ use std:: cell:: Cell ;
3+ use std:: cmp;
14use std:: mem;
2- use std:: rc:: Rc ;
5+ use std:: process;
6+ use std:: ptr;
37use std:: slice;
4- use std:: vec;
8+
9+ struct Header {
10+ cap : usize ,
11+ len : usize ,
12+ refcount : Cell < usize > ,
13+ }
514
615pub ( crate ) struct RcVec < T > {
7- inner : Rc < Vec < T > > ,
16+ first : * mut T ,
817}
918
1019pub ( crate ) struct RcVecBuilder < T > {
11- inner : Vec < T > ,
20+ first : * mut T ,
1221}
1322
1423pub ( crate ) struct RcVecMut < ' a , T > {
15- inner : & ' a mut Vec < T > ,
24+ first : & ' a mut * mut T ,
1625}
1726
1827#[ derive( Clone ) ]
1928pub ( crate ) struct RcVecIntoIter < T > {
20- inner : vec:: IntoIter < T > ,
29+ first : * mut T ,
30+ cur : * mut T ,
31+ }
32+
33+ unsafe fn header < ' a , T > ( first : * mut T ) -> & ' a Header {
34+ & * ( first as * const Header ) . offset ( -1 )
35+ }
36+
37+ unsafe fn header_mut < ' a , T > ( first : * mut T ) -> & ' a mut Header {
38+ & mut * ( first as * mut Header ) . offset ( -1 )
39+ }
40+
41+ unsafe fn allocation_layout < T > ( first : * mut T ) -> ( * mut u8 , Layout ) {
42+ // Alignment of the allocation.
43+ let align = cmp:: max ( mem:: align_of :: < T > ( ) , mem:: align_of :: < Header > ( ) ) ;
44+
45+ // Round up Header's size to a multiple of allocation's alignment.
46+ let mut header_size = mem:: size_of :: < Header > ( ) ;
47+ header_size = ( header_size + align - 1 ) / align * align;
48+
49+ let allocation = ( first as * mut u8 ) . sub ( header_size) ;
50+ let total_size = header_size + header ( first) . cap * mem:: size_of :: < T > ( ) ;
51+ let layout = Layout :: from_size_align_unchecked ( total_size, align) ;
52+ ( allocation, layout)
2153}
2254
2355impl < T > RcVec < T > {
2456 pub fn is_empty ( & self ) -> bool {
25- self . inner . is_empty ( )
57+ self . len ( ) == 0
2658 }
2759
2860 pub fn len ( & self ) -> usize {
29- self . inner . len ( )
61+ self . header ( ) . len
3062 }
3163
3264 pub fn iter ( & self ) -> slice:: Iter < T > {
33- self . inner . iter ( )
65+ let len = self . len ( ) ;
66+ unsafe { slice:: from_raw_parts ( self . first , len) } . iter ( )
3467 }
3568
3669 pub fn make_mut ( & mut self ) -> RcVecMut < T >
3770 where
3871 T : Clone ,
3972 {
73+ let header = self . header ( ) ;
74+ let refcount = header. refcount . get ( ) ;
75+ if refcount > 1 {
76+ let mut builder = RcVecBuilder :: new ( ) ;
77+ builder. extend ( self . iter ( ) . cloned ( ) ) ;
78+ // NOTE: assumes that none of the clones on the previous line
79+ // resulted in self's refcount changing. The public API of RcVec
80+ // does not expose any way to form cyclic structures.
81+ header. refcount . set ( refcount - 1 ) ;
82+ self . first = builder. first ;
83+ mem:: forget ( builder) ;
84+ }
4085 RcVecMut {
41- inner : Rc :: make_mut ( & mut self . inner ) ,
86+ first : & mut self . first ,
4287 }
4388 }
4489
4590 pub fn get_mut ( & mut self ) -> Option < RcVecMut < T > > {
46- let inner = Rc :: get_mut ( & mut self . inner ) ?;
47- Some ( RcVecMut { inner } )
91+ if self . header ( ) . refcount . get ( ) > 1 {
92+ None
93+ } else {
94+ Some ( RcVecMut {
95+ first : & mut self . first ,
96+ } )
97+ }
4898 }
4999
50- pub fn make_owned ( mut self ) -> RcVecBuilder < T >
100+ pub fn make_owned ( self ) -> RcVecBuilder < T >
51101 where
52102 T : Clone ,
53103 {
54- let vec = if let Some ( owned) = Rc :: get_mut ( & mut self . inner ) {
55- mem:: replace ( owned, Vec :: new ( ) )
104+ let header = self . header ( ) ;
105+ let refcount = header. refcount . get ( ) ;
106+ let first;
107+ if refcount > 1 {
108+ let mut builder = RcVecBuilder :: new ( ) ;
109+ builder. extend ( self . iter ( ) . cloned ( ) ) ;
110+ header. refcount . set ( refcount - 1 ) ;
111+ first = builder. first ;
112+ mem:: forget ( builder) ;
56113 } else {
57- Vec :: clone ( & self . inner )
58- } ;
59- RcVecBuilder { inner : vec }
114+ first = self . first ;
115+ }
116+ mem:: forget ( self ) ;
117+ RcVecBuilder { first }
118+ }
119+
120+ fn header ( & self ) -> & Header {
121+ unsafe { header ( self . first ) }
60122 }
61123}
62124
63125impl < T > RcVecBuilder < T > {
64126 pub fn new ( ) -> Self {
65- RcVecBuilder { inner : Vec :: new ( ) }
127+ Self :: with_capacity ( 8 )
66128 }
67129
68130 pub fn with_capacity ( cap : usize ) -> Self {
69- RcVecBuilder {
70- inner : Vec :: with_capacity ( cap) ,
131+ assert ! ( mem:: size_of:: <T >( ) > 0 ) ;
132+
133+ // Alignment of the allocation.
134+ let align = cmp:: max ( mem:: align_of :: < T > ( ) , mem:: align_of :: < Header > ( ) ) ;
135+
136+ // Round up Header's size to a multiple of allocation's alignment.
137+ let mut header_size = mem:: size_of :: < Header > ( ) ;
138+ header_size = ( header_size + align - 1 ) / align * align;
139+
140+ let total_size = mem:: size_of :: < T > ( )
141+ . saturating_mul ( cap)
142+ . saturating_add ( header_size) ;
143+ let layout = match Layout :: from_size_align ( total_size, align) {
144+ Ok ( layout) => layout,
145+ Err ( _) => process:: abort ( ) ,
146+ } ;
147+
148+ unsafe {
149+ let ptr = alloc:: alloc ( layout) ;
150+ let first = ptr. add ( header_size) as * mut T ;
151+ ( first as * mut Header ) . offset ( -1 ) . write ( Header {
152+ cap,
153+ len : 0 ,
154+ refcount : Cell :: new ( 1 ) ,
155+ } ) ;
156+ RcVecBuilder { first }
71157 }
72158 }
73159
74160 pub fn push ( & mut self , element : T ) {
75- self . inner . push ( element) ;
161+ self . as_mut ( ) . push ( element) ;
76162 }
77163
78164 pub fn extend ( & mut self , iter : impl IntoIterator < Item = T > ) {
79- self . inner . extend ( iter) ;
165+ self . as_mut ( ) . extend ( iter) ;
80166 }
81167
82168 pub fn as_mut ( & mut self ) -> RcVecMut < T > {
83169 RcVecMut {
84- inner : & mut self . inner ,
170+ first : & mut self . first ,
85171 }
86172 }
87173
88174 pub fn build ( self ) -> RcVec < T > {
89- RcVec {
90- inner : Rc :: new ( self . inner ) ,
91- }
175+ let first = self . first ;
176+ mem :: forget ( self ) ;
177+ RcVec { first }
92178 }
93179}
94180
95181impl < ' a , T > RcVecMut < ' a , T > {
96182 pub fn push ( & mut self , element : T ) {
97- self . inner . push ( element) ;
183+ self . reserve ( 1 ) ;
184+ let header = unsafe { header_mut ( * self . first ) } ;
185+ unsafe { ptr:: write ( self . first . add ( header. len ) , element) } ;
186+ header. len += 1 ;
98187 }
99188
100- pub fn extend ( & mut self , iter : impl IntoIterator < Item = T > ) {
101- self . inner . extend ( iter) ;
189+ pub fn extend ( & mut self , elements : impl IntoIterator < Item = T > ) {
190+ let iter = elements. into_iter ( ) ;
191+ self . reserve ( iter. size_hint ( ) . 0 ) ;
192+ iter. for_each ( |element| self . push ( element) ) ;
102193 }
103194
104195 pub fn pop ( & mut self ) -> Option < T > {
105- self . inner . pop ( )
196+ unsafe {
197+ let header = header_mut ( * self . first ) ;
198+ header. len = header. len . checked_sub ( 1 ) ?;
199+ Some ( ptr:: read ( self . first . add ( header. len ) ) )
200+ }
106201 }
107202
108203 pub fn as_mut ( & mut self ) -> RcVecMut < T > {
109- RcVecMut { inner : self . inner }
204+ RcVecMut { first : self . first }
205+ }
206+
207+ fn reserve ( & mut self , additional : usize ) {
208+ let header = unsafe { header ( * self . first ) } ;
209+ let required_capacity = header. len . saturating_add ( additional) ;
210+ if header. cap >= required_capacity {
211+ return ;
212+ }
213+
214+ let min_new_capacity = cmp:: max ( 8 , header. cap . saturating_mul ( 2 ) ) ;
215+ let new_capacity = cmp:: max ( required_capacity, min_new_capacity) ;
216+
217+ // Move ownership of the old allocation.
218+ let small = RcVecBuilder { first : * self . first } ;
219+
220+ // Move elements into new allocation.
221+ let mut big = RcVecBuilder :: with_capacity ( new_capacity) ;
222+ big. extend ( small. into_iter ( ) ) ;
223+
224+ // Self becomes big.
225+ * self . first = big. first ;
226+ mem:: forget ( big) ;
110227 }
111228}
112229
113230impl < T > Clone for RcVec < T > {
114231 fn clone ( & self ) -> Self {
115- RcVec {
116- inner : Rc :: clone ( & self . inner ) ,
117- }
232+ let header = self . header ( ) ;
233+ let count = header. refcount . get ( ) . checked_add ( 1 ) . unwrap ( ) ;
234+ header. refcount . set ( count) ;
235+ RcVec { first : self . first }
118236 }
119237}
120238
@@ -123,20 +241,68 @@ impl<T> IntoIterator for RcVecBuilder<T> {
123241 type IntoIter = RcVecIntoIter < T > ;
124242
125243 fn into_iter ( self ) -> Self :: IntoIter {
126- RcVecIntoIter {
127- inner : self . inner . into_iter ( ) ,
128- }
244+ let first = self . first ;
245+ mem :: forget ( self ) ;
246+ RcVecIntoIter { first , cur : first }
129247 }
130248}
131249
132250impl < T > Iterator for RcVecIntoIter < T > {
133251 type Item = T ;
134252
135253 fn next ( & mut self ) -> Option < Self :: Item > {
136- self . inner . next ( )
254+ unsafe {
255+ let len = header ( self . first ) . len ;
256+ if self . cur < self . first . add ( len) {
257+ let element = ptr:: read ( self . cur ) ;
258+ self . cur = self . cur . add ( 1 ) ;
259+ Some ( element)
260+ } else {
261+ None
262+ }
263+ }
137264 }
138265
139266 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
140- self . inner . size_hint ( )
267+ let end = unsafe { self . first . add ( header ( self . first ) . len ) } ;
268+ let remaining = ( end as usize - self . cur as usize ) / mem:: size_of :: < T > ( ) ;
269+ ( remaining, Some ( remaining) )
270+ }
271+ }
272+
273+ impl < T > Drop for RcVec < T > {
274+ fn drop ( & mut self ) {
275+ let header = self . header ( ) ;
276+ let refcount = header. refcount . get ( ) ;
277+ if refcount > 1 {
278+ header. refcount . set ( refcount - 1 ) ;
279+ } else {
280+ drop ( RcVecBuilder { first : self . first } ) ;
281+ }
282+ }
283+ }
284+
285+ impl < T > Drop for RcVecBuilder < T > {
286+ fn drop ( & mut self ) {
287+ unsafe {
288+ let len = header ( self . first ) . len ;
289+ let slice = slice:: from_raw_parts_mut ( self . first , len) ;
290+ ptr:: drop_in_place ( slice) ;
291+ let ( ptr, layout) = allocation_layout ( self . first ) ;
292+ alloc:: dealloc ( ptr, layout) ;
293+ }
294+ }
295+ }
296+
297+ impl < T > Drop for RcVecIntoIter < T > {
298+ fn drop ( & mut self ) {
299+ unsafe {
300+ let len = header ( self . first ) . len ;
301+ let offset = ( self . cur as usize - self . first as usize ) / mem:: size_of :: < T > ( ) ;
302+ let slice = slice:: from_raw_parts_mut ( self . cur , len - offset) ;
303+ ptr:: drop_in_place ( slice) ;
304+ let ( ptr, layout) = allocation_layout ( self . first ) ;
305+ alloc:: dealloc ( ptr, layout) ;
306+ }
141307 }
142308}
0 commit comments