@@ -4,57 +4,65 @@ use crate::NonZeroLayout;
4
4
use crate :: LocalAlloc ;
5
5
6
6
/// An allocation without tracked lifetime.
7
+ #[ derive( Copy , Clone ) ]
7
8
pub struct Allocation {
8
9
ptr : NonNull < u8 > ,
9
10
layout : NonZeroLayout ,
10
11
}
11
12
12
13
/// A references to an allocator.
13
14
///
14
- /// Allocations must be live for the lifetime of `self`. That is one must be able to move the
15
- /// `self` and keep all allocations. In particular, a reference to a [`LocalAlloc`] is an
16
- /// `AllocRef`.
15
+ /// Allocations created from this instance are valid for the lifetime of `self`. That is one must
16
+ /// be able to move the `self` and all allocations remain valid. In particular, a reference to a
17
+ /// [`LocalAlloc`] is an `AllocRef` as it is an immutable pin.
18
+ ///
19
+ /// An allocation is said to be live when it is valid and has not been passed to `dealloc` and has
20
+ /// not been passed to `realloc` that returned `Some(_)`.
21
+ ///
22
+ /// Note that all methods require being passed some existing allocation, even if they do not
23
+ /// consume it. See `InitialAllocRef` for those that do not.
17
24
///
18
25
/// [`LocalAlloc`]: trait.LocalAlloc.html
19
26
pub unsafe trait AllocRef {
20
27
/// Allocate one block of memory.
21
28
///
22
- /// The callee guarantees that a successful return contains a pointer that is valid for **at
23
- /// least** the layout requested by the caller.
24
- fn alloc ( & mut self , layout : NonZeroLayout ) -> Option < Allocation > ;
25
-
26
- /// Deallocate a block previously allocated.
27
- /// # Safety
28
- /// The caller must ensure that:
29
- /// * `alloc` has been previously returned from a call to `alloc`.
30
- /// * There are no more pointer to the allocation.
31
- unsafe fn dealloc ( & mut self , alloc : Allocation ) ;
29
+ /// The `existing` allocation can be used by the `AllocRef` to uniquely identify the allocator
30
+ /// that is used internaly. It must be valid for the same `AllocRef`.
31
+ ///
32
+ /// The callee guarantees that a successful return contains a pointer that fits the layout
33
+ /// requested by the caller and the layout in the struct is the same as requested.
34
+ unsafe fn alloc_from ( & mut self , existing : Allocation , layout : NonZeroLayout ) -> Option < Allocation > ;
32
35
33
36
/// Allocate a block of memory initialized with zeros.
34
37
///
35
- /// The callee guarantees that a successful return contains a pointer that is valid for **at
36
- /// least** the layout requested by the caller and the contiguous region of bytes, starting at
37
- /// the pointer and with the size of the returned layout, is initialized and zeroed.
38
- fn alloc_zeroed ( & mut self , layout : NonZeroLayout )
38
+ /// The callee guarantees that a successful return contains a pointer that fits the layout
39
+ /// requested by the caller and the layout in the struct is the same as requested.
40
+ unsafe fn alloc_zeroed_from ( & mut self , existing : Allocation , layout : NonZeroLayout )
39
41
-> Option < Allocation >
40
42
{
41
- let allocation = self . alloc ( layout) ?;
42
- unsafe {
43
- write_bytes ( allocation. ptr . as_ptr ( ) , 0u8 , allocation. layout . size ( ) . into ( ) ) ;
44
- }
43
+ let allocation = self . alloc ( existing, layout) ?;
44
+ write_bytes ( allocation. ptr . as_ptr ( ) , 0u8 , allocation. layout . size ( ) . into ( ) ) ;
45
45
Some ( allocation)
46
46
}
47
47
48
+ /// Deallocate a block previously allocated.
49
+ /// # Safety
50
+ /// The caller must ensure that:
51
+ /// * `alloc` has been previously returned from a call to `alloc`.
52
+ /// * There are no more pointer to the allocation.
53
+ unsafe fn dealloc ( & mut self , alloc : Allocation ) ;
54
+
48
55
/// Change the layout of a block previously allocated.
49
56
///
50
- /// The callee guarantees that a successful return contains a pointer that is valid for **at
51
- /// least** the layout requested by the caller and the contiguous region of bytes, starting at
52
- /// the pointer and with the size of the returned layout, is initialized with the prefix of the
53
- /// previous allocation that is still valid.
57
+ /// The callee guarantees that a successful return contains a pointer that it fits the layout
58
+ /// requested by the caller and the contiguous region of bytes, starting at the pointer and
59
+ /// with the size of the returned layout, is initialized with the prefix of the previous
60
+ /// allocation that is still valid, and that the layout in the returned struct is the same as
61
+ /// requested.
54
62
unsafe fn realloc ( & mut self , alloc : Allocation , layout : NonZeroLayout )
55
63
-> Option < Allocation >
56
64
{
57
- let new_alloc = self . alloc ( layout) ?;
65
+ let new_alloc = self . alloc ( alloc , layout) ?;
58
66
copy_nonoverlapping (
59
67
alloc. ptr . as_ptr ( ) ,
60
68
new_alloc. ptr . as_ptr ( ) ,
@@ -63,6 +71,29 @@ pub unsafe trait AllocRef {
63
71
}
64
72
}
65
73
74
+ /// A trait for an `AllocRef` that requires no existing allocation to allocate.
75
+ pub unsafe trait InitialAllocRef : AllocRef {
76
+ /// Allocate one block of memory.
77
+ ///
78
+ /// The callee guarantees that a successful return contains a pointer that fits the layout
79
+ /// requested by the caller and the layout in the struct is the same as requested.
80
+ fn alloc ( & mut self , layout : NonZeroLayout ) -> Option < Allocation > ;
81
+
82
+ /// Allocate a block of memory initialized with zeros.
83
+ ///
84
+ /// The callee guarantees that a successful return contains a pointer that fits the layout
85
+ /// requested by the caller and the layout in the struct is the same as requested.
86
+ fn alloc_zeroed ( & mut self , layout : NonZeroLayout )
87
+ -> Option < Allocation >
88
+ {
89
+ let allocation = InitialAllocRef :: alloc ( self , layout) ?;
90
+ unsafe {
91
+ write_bytes ( allocation. ptr . as_ptr ( ) , 0u8 , allocation. layout . size ( ) . into ( ) ) ;
92
+ }
93
+ Some ( allocation)
94
+ }
95
+ }
96
+
66
97
impl Allocation {
67
98
pub ( crate ) fn from_local ( alloc : crate :: local:: Allocation ) -> Self {
68
99
Allocation {
@@ -89,18 +120,18 @@ impl Allocation {
89
120
unsafe impl < ' rf , T > AllocRef for & ' rf T
90
121
where T : LocalAlloc < ' rf >
91
122
{
92
- fn alloc ( & mut self , layout : NonZeroLayout ) -> Option < Allocation > {
93
- LocalAlloc :: < ' rf > :: alloc ( * self , layout) . map ( Allocation :: from_local )
123
+ unsafe fn alloc ( & mut self , _ : Allocation , layout : NonZeroLayout ) -> Option < Allocation > {
124
+ InitialAllocRef :: alloc ( self , layout)
94
125
}
95
126
96
- unsafe fn dealloc ( & mut self , alloc : Allocation ) {
97
- LocalAlloc :: < ' rf > :: dealloc ( * self , alloc. into_local ( ) )
98
- }
99
-
100
- fn alloc_zeroed ( & mut self , layout : NonZeroLayout )
127
+ unsafe fn alloc_zeroed ( & mut self , _: Allocation , layout : NonZeroLayout )
101
128
-> Option < Allocation >
102
129
{
103
- LocalAlloc :: < ' rf > :: alloc_zeroed ( * self , layout) . map ( Allocation :: from_local)
130
+ InitialAllocRef :: alloc_zeroed ( self , layout)
131
+ }
132
+
133
+ unsafe fn dealloc ( & mut self , alloc : Allocation ) {
134
+ LocalAlloc :: < ' rf > :: dealloc ( * self , alloc. into_local ( ) )
104
135
}
105
136
106
137
unsafe fn realloc ( & mut self , alloc : Allocation , layout : NonZeroLayout )
@@ -110,3 +141,15 @@ unsafe impl<'rf, T> AllocRef for &'rf T
110
141
. map ( Allocation :: from_local)
111
142
}
112
143
}
144
+
145
+ unsafe impl < ' rf , T > InitialAllocRef for & ' rf T
146
+ where T : LocalAlloc < ' rf >
147
+ {
148
+ fn alloc ( & mut self , layout : NonZeroLayout ) -> Option < Allocation > {
149
+ LocalAlloc :: < ' rf > :: alloc ( * self , layout) . map ( Allocation :: from_local)
150
+ }
151
+
152
+ fn alloc_zeroed ( & mut self , layout : NonZeroLayout ) -> Option < Allocation > {
153
+ LocalAlloc :: < ' rf > :: alloc_zeroed ( * self , layout) . map ( Allocation :: from_local)
154
+ }
155
+ }
0 commit comments