@@ -4,57 +4,65 @@ use crate::NonZeroLayout;
44use crate :: LocalAlloc ;
55
66/// An allocation without tracked lifetime.
7+ #[ derive( Copy , Clone ) ]
78pub struct Allocation {
89 ptr : NonNull < u8 > ,
910 layout : NonZeroLayout ,
1011}
1112
1213/// A references to an allocator.
1314///
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.
1724///
1825/// [`LocalAlloc`]: trait.LocalAlloc.html
1926pub unsafe trait AllocRef {
2027 /// Allocate one block of memory.
2128 ///
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 > ;
3235
3336 /// Allocate a block of memory initialized with zeros.
3437 ///
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 )
3941 -> Option < Allocation >
4042 {
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 ( ) ) ;
4545 Some ( allocation)
4646 }
4747
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+
4855 /// Change the layout of a block previously allocated.
4956 ///
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.
5462 unsafe fn realloc ( & mut self , alloc : Allocation , layout : NonZeroLayout )
5563 -> Option < Allocation >
5664 {
57- let new_alloc = self . alloc ( layout) ?;
65+ let new_alloc = self . alloc ( alloc , layout) ?;
5866 copy_nonoverlapping (
5967 alloc. ptr . as_ptr ( ) ,
6068 new_alloc. ptr . as_ptr ( ) ,
@@ -63,6 +71,29 @@ pub unsafe trait AllocRef {
6371 }
6472}
6573
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+
6697impl Allocation {
6798 pub ( crate ) fn from_local ( alloc : crate :: local:: Allocation ) -> Self {
6899 Allocation {
@@ -89,18 +120,18 @@ impl Allocation {
89120unsafe impl < ' rf , T > AllocRef for & ' rf T
90121 where T : LocalAlloc < ' rf >
91122{
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)
94125 }
95126
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 )
101128 -> Option < Allocation >
102129 {
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 ( ) )
104135 }
105136
106137 unsafe fn realloc ( & mut self , alloc : Allocation , layout : NonZeroLayout )
@@ -110,3 +141,15 @@ unsafe impl<'rf, T> AllocRef for &'rf T
110141 . map ( Allocation :: from_local)
111142 }
112143}
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