25
25
//! drop(pool);
26
26
//! ```
27
27
28
- use std:: alloc:: { alloc, dealloc, handle_alloc_error, Layout } ;
28
+ use std:: alloc:: { alloc, dealloc, handle_alloc_error, realloc, Layout } ;
29
+ use std:: fmt;
29
30
use std:: mem;
30
31
use std:: ops:: { Deref , DerefMut } ;
31
32
use std:: ptr:: { self , NonNull } ;
32
33
use std:: sync:: Mutex ;
33
34
34
35
/// A pool of byte slices, that reuses memory.
36
+ #[ derive( Debug ) ]
35
37
pub struct BytePool {
36
38
list : Mutex < Vec < RawBlock > > ,
37
39
}
@@ -41,11 +43,29 @@ pub struct RawBlock {
41
43
layout : Layout ,
42
44
}
43
45
46
+ unsafe impl Sync for RawBlock { }
47
+ unsafe impl Send for RawBlock { }
48
+
49
+ #[ cfg( feature = "stable_deref" ) ]
50
+ unsafe impl stable_deref_trait:: StableDeref for RawBlock { }
51
+
44
52
pub struct Block < ' a > {
45
53
data : mem:: ManuallyDrop < RawBlock > ,
46
54
pool : & ' a BytePool ,
47
55
}
48
56
57
+ impl fmt:: Debug for Block < ' _ > {
58
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
59
+ f. debug_struct ( "Block" ) . field ( "data" , & self . data ) . finish ( )
60
+ }
61
+ }
62
+
63
+ impl fmt:: Debug for RawBlock {
64
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
65
+ write ! ( f, "RawBlock({:?})" , self . deref( ) )
66
+ }
67
+ }
68
+
49
69
impl Default for BytePool {
50
70
fn default ( ) -> Self {
51
71
BytePool {
@@ -103,7 +123,7 @@ impl<'a> Drop for Block<'a> {
103
123
}
104
124
105
125
impl RawBlock {
106
- pub fn alloc ( size : usize ) -> Self {
126
+ fn alloc ( size : usize ) -> Self {
107
127
// TODO: consider caching the layout
108
128
let layout = layout_for_size ( size) ;
109
129
debug_assert ! ( layout. size( ) > 0 ) ;
@@ -114,6 +134,24 @@ impl RawBlock {
114
134
layout,
115
135
}
116
136
}
137
+
138
+ fn grow ( & mut self , new_size : usize ) {
139
+ // TODO: use grow_in_place once it stablizies and possibly via a flag.
140
+ assert ! ( new_size > 0 ) ;
141
+ let new_layout = Layout :: from_size_align ( new_size, self . layout . align ( ) ) . unwrap ( ) ;
142
+ let new_ptr = unsafe { realloc ( self . ptr . as_mut ( ) , self . layout , new_layout. size ( ) ) } ;
143
+ self . ptr = NonNull :: new ( new_ptr) . unwrap_or_else ( || handle_alloc_error ( self . layout ) ) ;
144
+ self . layout = new_layout;
145
+ }
146
+
147
+ fn shrink ( & mut self , new_size : usize ) {
148
+ // TODO: use shrink_in_place once it stablizies and possibly via a flag.
149
+ assert ! ( new_size > 0 ) ;
150
+ let new_layout = Layout :: from_size_align ( new_size, self . layout . align ( ) ) . unwrap ( ) ;
151
+ let new_ptr = unsafe { realloc ( self . ptr . as_mut ( ) , self . layout , new_layout. size ( ) ) } ;
152
+ self . ptr = NonNull :: new ( new_ptr) . unwrap_or_else ( || handle_alloc_error ( self . layout ) ) ;
153
+ self . layout = new_layout;
154
+ }
117
155
}
118
156
119
157
impl Drop for RawBlock {
@@ -141,12 +179,26 @@ impl DerefMut for RawBlock {
141
179
}
142
180
143
181
impl < ' a > Block < ' a > {
144
- pub fn new ( data : RawBlock , pool : & ' a BytePool ) -> Self {
182
+ fn new ( data : RawBlock , pool : & ' a BytePool ) -> Self {
145
183
Block {
146
184
data : mem:: ManuallyDrop :: new ( data) ,
147
185
pool,
148
186
}
149
187
}
188
+
189
+ /// Resizes a block to a new size
190
+ pub fn realloc ( & mut self , new_size : usize ) {
191
+ if new_size < self . size ( ) {
192
+ self . data . shrink ( new_size) ;
193
+ } else if new_size > self . size ( ) {
194
+ self . data . grow ( new_size) ;
195
+ }
196
+ }
197
+
198
+ /// Returns the amount of bytes this block has.
199
+ pub fn size ( & self ) -> usize {
200
+ self . data . layout . size ( )
201
+ }
150
202
}
151
203
152
204
impl < ' a > Deref for Block < ' a > {
@@ -194,4 +246,27 @@ mod tests {
194
246
}
195
247
}
196
248
}
249
+
250
+ #[ test]
251
+ fn realloc ( ) {
252
+ let pool = BytePool :: new ( ) ;
253
+
254
+ let mut buf = pool. alloc ( 10 ) ;
255
+ assert_eq ! ( buf. len( ) , 10 ) ;
256
+ for el in buf. iter_mut ( ) {
257
+ * el = 1 ;
258
+ }
259
+
260
+ buf. realloc ( 512 ) ;
261
+ assert_eq ! ( buf. len( ) , 512 ) ;
262
+ for el in buf. iter ( ) . take ( 10 ) {
263
+ assert_eq ! ( * el, 1 ) ;
264
+ }
265
+
266
+ buf. realloc ( 5 ) ;
267
+ assert_eq ! ( buf. len( ) , 5 ) ;
268
+ for el in buf. iter ( ) {
269
+ assert_eq ! ( * el, 1 ) ;
270
+ }
271
+ }
197
272
}
0 commit comments