14
14
//! once, once the arena itself is destroyed. They do not support deallocation
15
15
//! of individual objects while the arena itself is still alive. The benefit
16
16
//! of an arena is very fast allocation; just a pointer bump.
17
+ //!
18
+ //! This crate has two arenas implemented: TypedArena, which is a simpler
19
+ //! arena but can only hold objects of a single type, and Arena, which is a
20
+ //! more complex, slower Arena which can hold objects of any type.
17
21
18
22
#![ crate_id = "arena#0.11.0-pre" ]
19
23
#![ crate_type = "rlib" ]
@@ -56,41 +60,42 @@ impl Chunk {
56
60
}
57
61
}
58
62
59
- // Arenas are used to quickly allocate objects that share a
60
- // lifetime. The arena uses ~[u8] vectors as a backing store to
61
- // allocate objects from. For each allocated object, the arena stores
62
- // a pointer to the type descriptor followed by the
63
- // object. (Potentially with alignment padding after each of them.)
64
- // When the arena is destroyed, it iterates through all of its chunks,
65
- // and uses the tydesc information to trace through the objects,
66
- // calling the destructors on them.
67
- // One subtle point that needs to be addressed is how to handle
68
- // failures while running the user provided initializer function. It
69
- // is important to not run the destructor on uninitialized objects, but
70
- // how to detect them is somewhat subtle. Since alloc() can be invoked
71
- // recursively, it is not sufficient to simply exclude the most recent
72
- // object. To solve this without requiring extra space, we use the low
73
- // order bit of the tydesc pointer to encode whether the object it
74
- // describes has been fully initialized.
75
-
76
- // As an optimization, objects with destructors are stored in
77
- // different chunks than objects without destructors. This reduces
78
- // overhead when initializing plain-old-data and means we don't need
79
- // to waste time running the destructors of POD.
63
+ /// A slower reflection-based arena that can allocate objects of any type.
64
+ ///
65
+ /// This arena uses Vec<u8> as a backing store to allocate objects from. For
66
+ /// each allocated object, the arena stores a pointer to the type descriptor
67
+ /// followed by the object. (Potentially with alignment padding after each
68
+ /// element.) When the arena is destroyed, it iterates through all of its
69
+ /// chunks, and uses the tydesc information to trace through the objects,
70
+ /// calling the destructors on them. One subtle point that needs to be
71
+ /// addressed is how to handle failures while running the user provided
72
+ /// initializer function. It is important to not run the destructor on
73
+ /// uninitialized objects, but how to detect them is somewhat subtle. Since
74
+ /// alloc() can be invoked recursively, it is not sufficient to simply exclude
75
+ /// the most recent object. To solve this without requiring extra space, we
76
+ /// use the low order bit of the tydesc pointer to encode whether the object
77
+ /// it describes has been fully initialized.
78
+ ///
79
+ /// As an optimization, objects with destructors are stored in
80
+ /// different chunks than objects without destructors. This reduces
81
+ /// overhead when initializing plain-old-data and means we don't need
82
+ /// to waste time running the destructors of POD.
80
83
pub struct Arena {
81
84
// The head is separated out from the list as a unbenchmarked
82
- // microoptimization, to avoid needing to case on the list to
83
- // access the head.
85
+ // microoptimization, to avoid needing to case on the list to access the
86
+ // head.
84
87
head : Chunk ,
85
88
copy_head : Chunk ,
86
89
chunks : RefCell < Vec < Chunk > > ,
87
90
}
88
91
89
92
impl Arena {
93
+ /// Allocate a new Arena with 32 bytes preallocated.
90
94
pub fn new ( ) -> Arena {
91
95
Arena :: new_with_size ( 32 u)
92
96
}
93
97
98
+ /// Allocate a new Arena with `initial_size` bytes preallocated.
94
99
pub fn new_with_size ( initial_size : uint ) -> Arena {
95
100
Arena {
96
101
head : chunk ( initial_size, false ) ,
@@ -265,7 +270,8 @@ impl Arena {
265
270
}
266
271
}
267
272
268
- // The external interface
273
+ /// Allocate a new item in the arena, using `op` to initialize the value
274
+ /// and returning a reference to it.
269
275
#[ inline]
270
276
pub fn alloc < ' a , T > ( & ' a self , op: || -> T ) -> & ' a T {
271
277
unsafe {
@@ -313,7 +319,7 @@ fn test_arena_destructors_fail() {
313
319
} ) ;
314
320
}
315
321
316
- /// An arena that can hold objects of only one type.
322
+ /// A faster arena that can hold objects of only one type.
317
323
///
318
324
/// Safety note: Modifying objects in the arena that have already had their
319
325
/// `drop` destructors run can cause leaks, because the destructor will not
@@ -405,13 +411,13 @@ impl<T> TypedArenaChunk<T> {
405
411
}
406
412
407
413
impl < T > TypedArena < T > {
408
- /// Creates a new arena with preallocated space for 8 objects.
414
+ /// Creates a new TypedArena with preallocated space for 8 objects.
409
415
#[ inline]
410
416
pub fn new ( ) -> TypedArena < T > {
411
417
TypedArena :: with_capacity ( 8 )
412
418
}
413
419
414
- /// Creates a new arena with preallocated space for the given number of
420
+ /// Creates a new TypedArena with preallocated space for the given number of
415
421
/// objects.
416
422
#[ inline]
417
423
pub fn with_capacity ( capacity : uint ) -> TypedArena < T > {
@@ -423,7 +429,7 @@ impl<T> TypedArena<T> {
423
429
}
424
430
}
425
431
426
- /// Allocates an object into this arena .
432
+ /// Allocates an object in the TypedArena, returning a reference to it .
427
433
#[ inline]
428
434
pub fn alloc < ' a > ( & ' a self , object : T ) -> & ' a T {
429
435
unsafe {
0 commit comments