@@ -25,6 +25,16 @@ use crate::error::Error;
25
25
use crate :: fmt;
26
26
use crate :: ptr:: { self , NonNull } ;
27
27
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
+
28
38
/// The `AllocError` error indicates an allocation failure
29
39
/// that may be due to resource exhaustion or to
30
40
/// something wrong when combining the given input arguments with this
@@ -48,6 +58,30 @@ impl fmt::Display for AllocError {
48
58
}
49
59
}
50
60
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
+
51
85
/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of
52
86
/// data described via [`Layout`][].
53
87
///
@@ -107,6 +141,13 @@ impl fmt::Display for AllocError {
107
141
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
108
142
#[ const_trait]
109
143
pub 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
+
110
151
/// Attempts to allocate a block of memory.
111
152
///
112
153
/// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`.
@@ -129,6 +170,8 @@ pub unsafe trait Allocator {
129
170
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
130
171
fn allocate ( & self , layout : Layout ) -> Result < NonNull < [ u8 ] > , AllocError > ;
131
172
173
+ fn co_allocate ( & self , _layout : Layout , _result : & mut SliceAndMetaResult ) { panic ! ( "TODO" ) }
174
+
132
175
/// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
133
176
///
134
177
/// # Errors
@@ -151,6 +194,19 @@ pub unsafe trait Allocator {
151
194
Ok ( ptr)
152
195
}
153
196
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
+
154
210
/// Deallocates the memory referenced by `ptr`.
155
211
///
156
212
/// # Safety
@@ -162,6 +218,8 @@ pub unsafe trait Allocator {
162
218
/// [*fit*]: #memory-fitting
163
219
unsafe fn deallocate ( & self , ptr : NonNull < u8 > , layout : Layout ) ;
164
220
221
+ unsafe fn co_deallocate ( & self , _ptr_and_meta : PtrAndMeta , _layout : Layout ) { panic ! ( "TODO" ) }
222
+
165
223
/// Attempts to extend the memory block.
166
224
///
167
225
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -226,6 +284,37 @@ pub unsafe trait Allocator {
226
284
Ok ( new_ptr)
227
285
}
228
286
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
+
229
318
/// Behaves like `grow`, but also ensures that the new contents are set to zero before being
230
319
/// returned.
231
320
///
@@ -289,6 +378,37 @@ pub unsafe trait Allocator {
289
378
Ok ( new_ptr)
290
379
}
291
380
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
+
292
412
/// Attempts to shrink the memory block.
293
413
///
294
414
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -353,6 +473,37 @@ pub unsafe trait Allocator {
353
473
Ok ( new_ptr)
354
474
}
355
475
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
+
356
507
/// Creates a "by reference" adapter for this instance of `Allocator`.
357
508
///
358
509
/// The returned adapter also implements `Allocator` and will simply borrow this.
@@ -365,6 +516,7 @@ pub unsafe trait Allocator {
365
516
}
366
517
}
367
518
519
+ // @TODO
368
520
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
369
521
unsafe impl < A > Allocator for & A
370
522
where
0 commit comments