@@ -56,6 +56,14 @@ impl<T: Poolable> BytePool<T> {
56
56
/// The returned `Block` contains arbitrary data, and must be zeroed or overwritten,
57
57
/// in cases this is needed.
58
58
pub fn alloc ( & self , size : usize ) -> Block < ' _ , T > {
59
+ self . alloc_internal ( size, false )
60
+ }
61
+
62
+ pub fn alloc_and_fill ( & self , size : usize ) -> Block < ' _ , T > {
63
+ self . alloc_internal ( size, true )
64
+ }
65
+
66
+ pub fn alloc_internal ( & self , size : usize , fill : bool ) -> Block < ' _ , T > {
59
67
assert ! ( size > 0 , "Can not allocate empty blocks" ) ;
60
68
61
69
// check the last 4 blocks
@@ -64,9 +72,12 @@ impl<T: Poolable> BytePool<T> {
64
72
} else {
65
73
& self . list_large
66
74
} ;
67
- if let Some ( el) = list. pop ( ) {
68
- if el. capacity ( ) == size {
75
+ if let Some ( mut el) = list. pop ( ) {
76
+ if el. capacity ( ) >= size && el . capacity ( ) < size + 1024 {
69
77
// found one, reuse it
78
+ if fill {
79
+ el. resize ( size)
80
+ }
70
81
return Block :: new ( el, self ) ;
71
82
} else {
72
83
// put it back
@@ -75,7 +86,11 @@ impl<T: Poolable> BytePool<T> {
75
86
}
76
87
77
88
// allocate a new block
78
- let data = T :: alloc ( size) ;
89
+ let data = if fill {
90
+ T :: alloc_and_fill ( size)
91
+ } else {
92
+ T :: alloc ( size)
93
+ } ;
79
94
Block :: new ( data, self )
80
95
}
81
96
@@ -90,7 +105,8 @@ impl<T: Poolable> BytePool<T> {
90
105
91
106
impl < ' a , T : Poolable > Drop for Block < ' a , T > {
92
107
fn drop ( & mut self ) {
93
- let data = mem:: ManuallyDrop :: into_inner ( unsafe { ptr:: read ( & self . data ) } ) ;
108
+ let mut data = mem:: ManuallyDrop :: into_inner ( unsafe { ptr:: read ( & self . data ) } ) ;
109
+ data. reset ( ) ;
94
110
self . pool . push_raw_block ( data) ;
95
111
}
96
112
}
@@ -138,6 +154,41 @@ unsafe impl<'a, T: StableDeref + Poolable> StableDeref for Block<'a, T> {}
138
154
#[ cfg( test) ]
139
155
mod tests {
140
156
use super :: * ;
157
+ #[ test]
158
+ fn append ( ) {
159
+ let pool = BytePool :: < Vec < u8 > > :: new ( ) ;
160
+ let mut buf = pool. alloc ( 4 ) ;
161
+ assert_eq ! ( 0 , buf. len( ) ) ;
162
+ assert_eq ! ( 4 , buf. capacity( ) ) ;
163
+ buf. push ( 12u8 ) ;
164
+ assert_eq ! ( 1 , buf. len( ) ) ;
165
+ buf. extend_from_slice ( "hello" . as_bytes ( ) ) ;
166
+ assert_eq ! ( 6 , buf. len( ) ) ;
167
+ buf. clear ( ) ;
168
+ assert_eq ! ( 0 , buf. len( ) ) ;
169
+ assert ! ( buf. capacity( ) > 0 ) ;
170
+ }
171
+
172
+ #[ test]
173
+ fn len_and_capacity ( ) {
174
+ let pool = BytePool :: < Vec < u8 > > :: new ( ) ;
175
+ for i in 1 ..10 {
176
+ let buf = pool. alloc_and_fill ( i) ;
177
+ assert_eq ! ( buf. len( ) , i)
178
+ }
179
+ for i in 1 ..10 {
180
+ let buf = pool. alloc ( i) ;
181
+ assert_eq ! ( buf. len( ) , 0 )
182
+ }
183
+ for i in 1 ..10 {
184
+ let buf = pool. alloc_and_fill ( i * 10000 ) ;
185
+ assert_eq ! ( buf. len( ) , i * 10000 )
186
+ }
187
+ for i in 1 ..10 {
188
+ let buf = pool. alloc ( i * 10000 ) ;
189
+ assert_eq ! ( buf. len( ) , 0 )
190
+ }
191
+ }
141
192
142
193
#[ test]
143
194
fn basics_vec_u8 ( ) {
@@ -174,6 +225,7 @@ mod tests {
174
225
let _slice: & [ u8 ] = & buf;
175
226
176
227
assert_eq ! ( buf. capacity( ) , 10 ) ;
228
+ buf. resize ( 10 , 0 ) ;
177
229
for i in 0 ..10 {
178
230
buf[ i] = 1 ;
179
231
}
@@ -198,15 +250,15 @@ mod tests {
198
250
let pool1 = pool. clone ( ) ;
199
251
let h1 = std:: thread:: spawn ( move || {
200
252
for _ in 0 ..100 {
201
- let mut buf = pool1. alloc ( 64 ) ;
253
+ let mut buf = pool1. alloc_and_fill ( 64 ) ;
202
254
buf[ 10 ] = 10 ;
203
255
}
204
256
} ) ;
205
257
206
258
let pool2 = pool. clone ( ) ;
207
259
let h2 = std:: thread:: spawn ( move || {
208
260
for _ in 0 ..100 {
209
- let mut buf = pool2. alloc ( 64 ) ;
261
+ let mut buf = pool2. alloc_and_fill ( 64 ) ;
210
262
buf[ 10 ] = 10 ;
211
263
}
212
264
} ) ;
0 commit comments