1
1
//! Implements dynamically typed arenas, where any type of item can be allocated.
2
- extern crate typed_arena;
3
-
2
+ #![ deny( missing_docs) ]
4
3
use std:: marker:: PhantomData ;
5
4
use std:: cell:: RefCell ;
6
5
use std:: os:: raw:: c_void;
7
- use std:: { mem, ptr} ;
6
+ use std:: mem;
7
+ use std:: ptr:: { self , NonNull } ;
8
+ use std:: alloc:: Layout ;
8
9
9
- use typed_arena :: Arena ;
10
+ use bumpalo :: Bump ;
10
11
11
12
/// Marker trait that indicates whether or a `DynamicArena` may be sent across threads
12
13
pub trait SendAbility : Sized {
14
+ /// Create an arena corresponding to this type of thread-safety
13
15
fn create_arena < ' a > ( ) -> DynamicArena < ' a , Self > ;
14
16
}
15
17
/// Marker type that indicates you expect everything in the `DynamicArena` to be `Send`
@@ -102,7 +104,7 @@ pub type DynamicSendArena<'a> = DynamicArena<'a, Sendable>;
102
104
/// before they proceed to allocate the copyable struct.
103
105
pub struct DynamicArena < ' a , S = NonSend > {
104
106
/// The underlying arena, where we request that they allocate arbitrary bytes.
105
- handle : Arena < u8 > ,
107
+ handle : Bump ,
106
108
/// The list of untyped values we've allocated in the arena,
107
109
/// and whose drop functions need to be invoked.
108
110
///
@@ -130,10 +132,15 @@ impl DynamicArena<'static, NonSend> {
130
132
DynamicArena :: new_bounded ( )
131
133
}
132
134
}
133
- impl < ' a , S > DynamicArena < ' a , S > {
135
+ impl < ' a , S > DynamicArena < ' a , S > {
136
+ /// Create an arena with pre-allocated capacity for the specified number of items
137
+ /// and bytes.
138
+ ///
139
+ /// NOTE: The "item" capacity excludes `Copy` references that
140
+ /// don't need to be dropped.
134
141
pub fn with_capacity ( item_capacity : usize , byte_capacity : usize ) -> Self {
135
142
DynamicArena {
136
- handle : Arena :: with_capacity ( byte_capacity) ,
143
+ handle : Bump :: with_capacity ( byte_capacity) ,
137
144
items : RefCell :: new ( Vec :: with_capacity ( item_capacity) ) ,
138
145
marker : PhantomData ,
139
146
send : PhantomData
@@ -145,28 +152,47 @@ impl<'a, S> DynamicArena<'a, S> {
145
152
/// The bound on the item requires that `T: Copy`
146
153
/// to ensure there's no drop function that needs to be invoked.
147
154
#[ inline]
155
+ #[ allow( clippy:: mut_from_ref) ]
148
156
pub fn alloc_copy < T : Copy + Send > ( & self , value : T ) -> & mut T {
149
157
unsafe {
150
158
self . alloc_unchecked ( value)
151
159
}
152
160
}
153
161
/// Allocate the specified value in this arena,
154
- /// without ensuring that its drop function would be safe to invoke.
162
+ /// without calling its `Drop` function.
163
+ ///
164
+ /// Since this doesn't call the 'Drop' impleentation,
165
+ /// this function leaks the underlying memory.
155
166
///
156
- /// Additionally this function leaks the underlying memory,
157
- /// and never runs the destructor, so its ownership needs to be tracked seperately.
167
+ /// ## Safety
168
+ /// Technically, this function is safe to use.
169
+ /// However, it leaks memory unconditionally (without calling Drop).
158
170
#[ inline]
171
+ #[ allow( clippy:: mut_from_ref) ]
159
172
pub unsafe fn alloc_unchecked < T > ( & self , value : T ) -> & mut T {
160
- let ptr = ( * self . handle . alloc_uninitialized ( mem :: size_of :: < T > ( ) ) ) . as_ptr ( ) as * mut T ;
161
- ptr:: write ( ptr , value) ;
173
+ let ptr = self . alloc_layout ( Layout :: new :: < T > ( ) ) . as_ptr ( ) . cast :: < T > ( ) ;
174
+ ptr. write ( value) ;
162
175
& mut * ptr
163
176
}
177
+ /// Allocate space for an object with the specified layout
178
+ ///
179
+ /// The returned pointer points at uninitialized memory
180
+ ///
181
+ /// ## Safety
182
+ /// Technically, only the use of the memory is unsafe.
183
+ ///
184
+ /// It would theoretically be possible to mark this function safe,
185
+ /// just like [Bump::alloc_layout].
186
+ #[ inline]
187
+ pub unsafe fn alloc_layout ( & self , layout : Layout ) -> NonNull < u8 > {
188
+ self . handle . alloc_layout ( layout)
189
+ }
164
190
/// Dynamically drop the specified value,
165
191
/// invoking the drop function when the arena is dropped.
166
192
///
167
- /// This is unsafe because the drop function isn't necessarily safe to invoke,
168
- /// and the memory isn't nessicarrily .
169
- /// Not only are you assuming that ` ptr::drop_in_place` would be safe,
193
+ /// ## Safety
194
+ /// This assumes it's safe to drop the value at the same time the arena is dropped .
195
+ /// Not only are you assuming that [ ptr::drop_in_place] would be safe,
170
196
/// you're also assuming that the drop function won't reference any dangling pointers,
171
197
/// and that [dropchk](https://doc.rust-lang.org/nomicon/dropck.html) would be successful.
172
198
///
@@ -183,6 +209,11 @@ impl<'a, S> DynamicArena<'a, S> {
183
209
} )
184
210
}
185
211
}
212
+ /// Retrieve the underlying [bump allocator](bumpalo::Bump) for this arena
213
+ #[ inline]
214
+ pub fn as_bumpalo ( & self ) -> & ' _ bumpalo:: Bump {
215
+ & self . handle
216
+ }
186
217
}
187
218
impl < ' a > DynamicArena < ' a , Sendable > {
188
219
/// Create a new empty arena, bounded by the inferred lifetime for this type `'a`
@@ -191,7 +222,7 @@ impl<'a> DynamicArena<'a, Sendable> {
191
222
/// all items in the arena need to implement `Send`.
192
223
pub fn new_send ( ) -> Self {
193
224
DynamicArena {
194
- handle : Arena :: new ( ) ,
225
+ handle : Bump :: new ( ) ,
195
226
items : RefCell :: new ( Vec :: new ( ) ) ,
196
227
marker : PhantomData ,
197
228
send : PhantomData
@@ -205,6 +236,7 @@ impl<'a> DynamicArena<'a, Sendable> {
205
236
/// Additionally, since the arena is `Sendable`,
206
237
/// the bound on the item also requires that `T: Send`.
207
238
#[ inline]
239
+ #[ allow( clippy:: mut_from_ref) ]
208
240
pub fn alloc < T : Send + ' a > ( & self , value : T ) -> & mut T {
209
241
unsafe {
210
242
let target = self . alloc_unchecked ( value) ;
@@ -220,7 +252,7 @@ impl<'a> DynamicArena<'a, NonSend> {
220
252
/// the items in the arena don't necessarily need to implement `Send`.
221
253
pub fn new_bounded ( ) -> Self {
222
254
DynamicArena {
223
- handle : Arena :: new ( ) ,
255
+ handle : Bump :: new ( ) ,
224
256
items : RefCell :: new ( Vec :: new ( ) ) ,
225
257
marker : PhantomData ,
226
258
send : PhantomData
@@ -232,6 +264,7 @@ impl<'a> DynamicArena<'a, NonSend> {
232
264
/// The bound on this item requires that `T: 'a`
233
265
/// to ensure the drop function is safe to invoke.
234
266
#[ inline]
267
+ #[ allow( clippy:: mut_from_ref) ]
235
268
pub fn alloc < T : ' a > ( & self , value : T ) -> & mut T {
236
269
unsafe {
237
270
let target = self . alloc_unchecked ( value) ;
0 commit comments