@@ -59,6 +59,25 @@ impl fmt::Display for AllocError {
5959 }
6060}
6161
62+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
63+ #[ allow( missing_debug_implementations) ]
64+ pub struct PtrAndMeta {
65+ pub ptr : NonNull < u8 > ,
66+ pub meta : GlobalCoAllocMeta ,
67+ }
68+
69+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
70+ #[ allow( missing_debug_implementations) ]
71+ /// Used for results (from `CoAllocator`'s functions, where applicable).
72+ pub struct SliceAndMeta {
73+ pub slice : NonNull < [ u8 ] > ,
74+ pub meta : GlobalCoAllocMeta ,
75+ }
76+
77+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
78+ #[ allow( missing_debug_implementations) ]
79+ pub type SliceAndMetaResult = Result < SliceAndMeta , AllocError > ;
80+
6281/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of
6382/// data described via [`Layout`][].
6483///
@@ -140,6 +159,8 @@ pub unsafe trait Allocator {
140159 /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
141160 fn allocate ( & self , layout : Layout ) -> Result < NonNull < [ u8 ] > , AllocError > ;
142161
162+ fn co_allocate ( & self , _layout : Layout , _result : & mut SliceAndMetaResult ) { panic ! ( "TODO" ) }
163+
143164 /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
144165 ///
145166 /// # Errors
@@ -162,6 +183,19 @@ pub unsafe trait Allocator {
162183 Ok ( ptr)
163184 }
164185
186+ fn co_allocate_zeroed ( & self , layout : Layout , mut result : & mut SliceAndMetaResult ) {
187+ self . co_allocate ( layout, & mut result) ;
188+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
189+ // SAFETY: `alloc` returns a valid memory block
190+ unsafe {
191+ slice
192+ . as_non_null_ptr ( )
193+ . as_ptr ( )
194+ . write_bytes ( 0 , slice. len ( ) )
195+ }
196+ }
197+ }
198+
165199 /// Deallocates the memory referenced by `ptr`.
166200 ///
167201 /// # Safety
@@ -173,6 +207,8 @@ pub unsafe trait Allocator {
173207 /// [*fit*]: #memory-fitting
174208 unsafe fn deallocate ( & self , ptr : NonNull < u8 > , layout : Layout ) ;
175209
210+ unsafe fn co_deallocate ( & self , _ptr_and_meta : PtrAndMeta , _layout : Layout ) { panic ! ( "TODO" ) }
211+
176212 /// Attempts to extend the memory block.
177213 ///
178214 /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -237,6 +273,37 @@ pub unsafe trait Allocator {
237273 Ok ( new_ptr)
238274 }
239275
276+ unsafe fn co_grow (
277+ & self ,
278+ ptr_and_meta : PtrAndMeta ,
279+ old_layout : Layout ,
280+ new_layout : Layout ,
281+ mut result : & mut SliceAndMetaResult
282+ ) {
283+ debug_assert ! (
284+ new_layout. size( ) >= old_layout. size( ) ,
285+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
286+ ) ;
287+
288+ self . co_allocate ( new_layout, & mut result) ;
289+
290+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
291+ // SAFETY: because `new_layout.size()` must be greater than or equal to
292+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
293+ // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
294+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
295+ // safe. The safety contract for `dealloc` must be upheld by the caller.
296+ unsafe {
297+ ptr:: copy_nonoverlapping (
298+ ptr_and_meta. ptr . as_ptr ( ) ,
299+ slice. as_mut_ptr ( ) ,
300+ old_layout. size ( ) ,
301+ ) ;
302+ self . co_deallocate ( ptr_and_meta, old_layout) ;
303+ }
304+ }
305+ }
306+
240307 /// Behaves like `grow`, but also ensures that the new contents are set to zero before being
241308 /// returned.
242309 ///
@@ -300,6 +367,37 @@ pub unsafe trait Allocator {
300367 Ok ( new_ptr)
301368 }
302369
370+ unsafe fn co_grow_zeroed (
371+ & self ,
372+ ptr_and_meta : PtrAndMeta ,
373+ old_layout : Layout ,
374+ new_layout : Layout ,
375+ mut result : & mut SliceAndMetaResult
376+ ) {
377+ debug_assert ! (
378+ new_layout. size( ) >= old_layout. size( ) ,
379+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
380+ ) ;
381+
382+ self . co_allocate_zeroed ( new_layout, & mut result) ;
383+
384+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
385+ // SAFETY: because `new_layout.size()` must be greater than or equal to
386+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
387+ // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
388+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
389+ // safe. The safety contract for `dealloc` must be upheld by the caller.
390+ unsafe {
391+ ptr:: copy_nonoverlapping (
392+ ptr_and_meta. ptr . as_ptr ( ) ,
393+ slice. as_mut_ptr ( ) ,
394+ old_layout. size ( ) ,
395+ ) ;
396+ self . co_deallocate ( ptr_and_meta, old_layout) ;
397+ }
398+ }
399+ }
400+
303401 /// Attempts to shrink the memory block.
304402 ///
305403 /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -364,6 +462,37 @@ pub unsafe trait Allocator {
364462 Ok ( new_ptr)
365463 }
366464
465+ unsafe fn co_shrink (
466+ & self ,
467+ ptr_and_meta : PtrAndMeta ,
468+ old_layout : Layout ,
469+ new_layout : Layout ,
470+ mut result : & mut SliceAndMetaResult
471+ ) {
472+ debug_assert ! (
473+ new_layout. size( ) <= old_layout. size( ) ,
474+ "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
475+ ) ;
476+
477+ self . co_allocate ( new_layout, & mut result) ;
478+
479+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
480+ // SAFETY: because `new_layout.size()` must be lower than or equal to
481+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
482+ // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet
483+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
484+ // safe. The safety contract for `dealloc` must be upheld by the caller.
485+ unsafe {
486+ ptr:: copy_nonoverlapping (
487+ ptr_and_meta. ptr . as_ptr ( ) ,
488+ slice. as_mut_ptr ( ) ,
489+ new_layout. size ( ) ,
490+ ) ;
491+ self . co_deallocate ( ptr_and_meta, old_layout) ;
492+ }
493+ }
494+ }
495+
367496 /// Creates a "by reference" adapter for this instance of `Allocator`.
368497 ///
369498 /// The returned adapter also implements `Allocator` and will simply borrow this.
0 commit comments