@@ -59,6 +59,25 @@ impl fmt::Display for AllocError {
59
59
}
60
60
}
61
61
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
+
62
81
/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of
63
82
/// data described via [`Layout`][].
64
83
///
@@ -140,6 +159,8 @@ pub unsafe trait Allocator {
140
159
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
141
160
fn allocate ( & self , layout : Layout ) -> Result < NonNull < [ u8 ] > , AllocError > ;
142
161
162
+ fn co_allocate ( & self , _layout : Layout , _result : & mut SliceAndMetaResult ) { panic ! ( "TODO" ) }
163
+
143
164
/// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
144
165
///
145
166
/// # Errors
@@ -162,6 +183,19 @@ pub unsafe trait Allocator {
162
183
Ok ( ptr)
163
184
}
164
185
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
+
165
199
/// Deallocates the memory referenced by `ptr`.
166
200
///
167
201
/// # Safety
@@ -173,6 +207,8 @@ pub unsafe trait Allocator {
173
207
/// [*fit*]: #memory-fitting
174
208
unsafe fn deallocate ( & self , ptr : NonNull < u8 > , layout : Layout ) ;
175
209
210
+ unsafe fn co_deallocate ( & self , _ptr_and_meta : PtrAndMeta , _layout : Layout ) { panic ! ( "TODO" ) }
211
+
176
212
/// Attempts to extend the memory block.
177
213
///
178
214
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -237,6 +273,37 @@ pub unsafe trait Allocator {
237
273
Ok ( new_ptr)
238
274
}
239
275
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
+
240
307
/// Behaves like `grow`, but also ensures that the new contents are set to zero before being
241
308
/// returned.
242
309
///
@@ -300,6 +367,37 @@ pub unsafe trait Allocator {
300
367
Ok ( new_ptr)
301
368
}
302
369
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
+
303
401
/// Attempts to shrink the memory block.
304
402
///
305
403
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
@@ -364,6 +462,37 @@ pub unsafe trait Allocator {
364
462
Ok ( new_ptr)
365
463
}
366
464
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
+
367
496
/// Creates a "by reference" adapter for this instance of `Allocator`.
368
497
///
369
498
/// The returned adapter also implements `Allocator` and will simply borrow this.
0 commit comments