@@ -25,6 +25,16 @@ use crate::error::Error;
2525use crate :: fmt;
2626use crate :: ptr:: { self , NonNull } ;
2727
28+ // @TODO Make this target-specific
29+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
30+ #[ allow( missing_debug_implementations) ]
31+ pub struct GlobalCoAllocMeta {
32+ //pub one: usize,
33+ /*pub two: usize,
34+ pub three: usize,
35+ pub four: usize,*/
36+ }
37+
2838/// The `AllocError` error indicates an allocation failure
2939/// that may be due to resource exhaustion or to
3040/// something wrong when combining the given input arguments with this
@@ -48,6 +58,30 @@ impl fmt::Display for AllocError {
4858 }
4959}
5060
61+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
62+ #[ allow( missing_debug_implementations) ]
63+ pub struct PtrAndMeta {
64+ pub ptr : NonNull < u8 > ,
65+ pub meta : GlobalCoAllocMeta ,
66+ }
67+
68+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
69+ #[ allow( missing_debug_implementations) ]
70+ /// Used for results (from `CoAllocator`'s functions, where applicable).
71+ pub struct SliceAndMeta {
72+ pub slice : NonNull < [ u8 ] > ,
73+ pub meta : GlobalCoAllocMeta ,
74+ }
75+
76+ #[ unstable( feature = "global_co_alloc_meta" , issue = "none" ) ]
77+ #[ allow( missing_debug_implementations) ]
78+ pub type SliceAndMetaResult = Result < SliceAndMeta , AllocError > ;
79+
80+ #[ unstable( feature = "global_co_alloc" , issue = "none" ) ]
81+ pub const fn co_alloc_metadata_num_slots < A : Allocator > ( ) -> usize {
82+ if A :: IS_CO_ALLOCATOR { 1 } else { 0 }
83+ }
84+
5185/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of
5286/// data described via [`Layout`][].
5387///
@@ -107,6 +141,13 @@ impl fmt::Display for AllocError {
107141#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
108142#[ const_trait]
109143pub unsafe trait Allocator {
144+ //const fn is_co_allocator() -> bool {false}
145+ // Can't have: const type Xyz;
146+ /// If this is any type with non-zero size, then the actual `Allocator` implementation supports cooperative functions (`co_*`) as first class citizens.
147+ //type IsCoAllocator = ();
148+ // It applies to the global (default) allocator only. And/or System allocator?! TODO
149+ const IS_CO_ALLOCATOR : bool = true ;
150+
110151 /// Attempts to allocate a block of memory.
111152 ///
112153 /// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`.
@@ -129,6 +170,8 @@ pub unsafe trait Allocator {
129170 /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
130171 fn allocate ( & self , layout : Layout ) -> Result < NonNull < [ u8 ] > , AllocError > ;
131172
173+ fn co_allocate ( & self , _layout : Layout , _result : & mut SliceAndMetaResult ) { panic ! ( "TODO" ) }
174+
132175 /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
133176 ///
134177 /// # Errors
@@ -151,6 +194,19 @@ pub unsafe trait Allocator {
151194 Ok ( ptr)
152195 }
153196
197+ fn co_allocate_zeroed ( & self , layout : Layout , mut result : & mut SliceAndMetaResult ) {
198+ self . co_allocate ( layout, & mut result) ;
199+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
200+ // SAFETY: `alloc` returns a valid memory block
201+ unsafe {
202+ slice
203+ . as_non_null_ptr ( )
204+ . as_ptr ( )
205+ . write_bytes ( 0 , slice. len ( ) )
206+ }
207+ }
208+ }
209+
154210 /// Deallocates the memory referenced by `ptr`.
155211 ///
156212 /// # Safety
@@ -162,6 +218,8 @@ pub unsafe trait Allocator {
162218 /// [*fit*]: #memory-fitting
163219 unsafe fn deallocate ( & self , ptr : NonNull < u8 > , layout : Layout ) ;
164220
221+ unsafe fn co_deallocate ( & self , _ptr_and_meta : PtrAndMeta , _layout : Layout ) { panic ! ( "TODO" ) }
222+
165223 /// Attempts to extend the memory block.
166224 ///
167225 /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -226,6 +284,37 @@ pub unsafe trait Allocator {
226284 Ok ( new_ptr)
227285 }
228286
287+ unsafe fn co_grow (
288+ & self ,
289+ ptr_and_meta : PtrAndMeta ,
290+ old_layout : Layout ,
291+ new_layout : Layout ,
292+ mut result : & mut SliceAndMetaResult
293+ ) {
294+ debug_assert ! (
295+ new_layout. size( ) >= old_layout. size( ) ,
296+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
297+ ) ;
298+
299+ self . co_allocate ( new_layout, & mut result) ;
300+
301+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
302+ // SAFETY: because `new_layout.size()` must be greater than or equal to
303+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
304+ // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
305+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
306+ // safe. The safety contract for `dealloc` must be upheld by the caller.
307+ unsafe {
308+ ptr:: copy_nonoverlapping (
309+ ptr_and_meta. ptr . as_ptr ( ) ,
310+ slice. as_mut_ptr ( ) ,
311+ old_layout. size ( ) ,
312+ ) ;
313+ self . co_deallocate ( ptr_and_meta, old_layout) ;
314+ }
315+ }
316+ }
317+
229318 /// Behaves like `grow`, but also ensures that the new contents are set to zero before being
230319 /// returned.
231320 ///
@@ -289,6 +378,37 @@ pub unsafe trait Allocator {
289378 Ok ( new_ptr)
290379 }
291380
381+ unsafe fn co_grow_zeroed (
382+ & self ,
383+ ptr_and_meta : PtrAndMeta ,
384+ old_layout : Layout ,
385+ new_layout : Layout ,
386+ mut result : & mut SliceAndMetaResult
387+ ) {
388+ debug_assert ! (
389+ new_layout. size( ) >= old_layout. size( ) ,
390+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
391+ ) ;
392+
393+ self . co_allocate_zeroed ( new_layout, & mut result) ;
394+
395+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
396+ // SAFETY: because `new_layout.size()` must be greater than or equal to
397+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
398+ // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
399+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
400+ // safe. The safety contract for `dealloc` must be upheld by the caller.
401+ unsafe {
402+ ptr:: copy_nonoverlapping (
403+ ptr_and_meta. ptr . as_ptr ( ) ,
404+ slice. as_mut_ptr ( ) ,
405+ old_layout. size ( ) ,
406+ ) ;
407+ self . co_deallocate ( ptr_and_meta, old_layout) ;
408+ }
409+ }
410+ }
411+
292412 /// Attempts to shrink the memory block.
293413 ///
294414 /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -353,6 +473,37 @@ pub unsafe trait Allocator {
353473 Ok ( new_ptr)
354474 }
355475
476+ unsafe fn co_shrink (
477+ & self ,
478+ ptr_and_meta : PtrAndMeta ,
479+ old_layout : Layout ,
480+ new_layout : Layout ,
481+ mut result : & mut SliceAndMetaResult
482+ ) {
483+ debug_assert ! (
484+ new_layout. size( ) <= old_layout. size( ) ,
485+ "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
486+ ) ;
487+
488+ self . co_allocate ( new_layout, & mut result) ;
489+
490+ if let Ok ( SliceAndMeta { slice, ..} ) = result {
491+ // SAFETY: because `new_layout.size()` must be lower than or equal to
492+ // `old_layout.size()`, both the old and new memory allocation are valid for reads and
493+ // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet
494+ // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is
495+ // safe. The safety contract for `dealloc` must be upheld by the caller.
496+ unsafe {
497+ ptr:: copy_nonoverlapping (
498+ ptr_and_meta. ptr . as_ptr ( ) ,
499+ slice. as_mut_ptr ( ) ,
500+ new_layout. size ( ) ,
501+ ) ;
502+ self . co_deallocate ( ptr_and_meta, old_layout) ;
503+ }
504+ }
505+ }
506+
356507 /// Creates a "by reference" adapter for this instance of `Allocator`.
357508 ///
358509 /// The returned adapter also implements `Allocator` and will simply borrow this.
@@ -365,6 +516,7 @@ pub unsafe trait Allocator {
365516 }
366517}
367518
519+ // @TODO
368520#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
369521unsafe impl < A > Allocator for & A
370522where
0 commit comments