@@ -326,7 +326,7 @@ struct ExecutorJob {
326
326
...
327
327
328
328
/// Storage reserved for the executor
329
- var executorPrivate: (UInt , UInt )
329
+ public var executorPrivate: (UInt , UInt )
330
330
331
331
/// Kinds of schedulable jobs.
332
332
@frozen
@@ -344,50 +344,90 @@ struct ExecutorJob {
344
344
}
345
345
346
346
/// What kind of job this is
347
- var kind: Kind
347
+ public var kind: Kind
348
348
...
349
349
}
350
350
```
351
351
352
- Finally, jobs of type ` JobKind.task ` have the ability to allocate task
353
- memory, using a stack disciplined allocator; this memory is
354
- automatically released when the task itself is released. We will
355
- expose some new functions on ` ExecutorJob ` to allow access to this
356
- facility:
352
+ Finally, jobs of type ` ExecutorJob.Kind.task ` have the ability to
353
+ allocate task memory, using a stack disciplined allocator; this memory
354
+ is automatically released when the task itself is released.
355
+
356
+ Rather than require users to test the job kind to discover this, which
357
+ would mean that they would not be able to use allocation on new job
358
+ types we might add in future, or on other existing job types that
359
+ might gain allocation support, it seems better to provide an interface
360
+ that will allow users to conditionally acquire an allocator. We are
361
+ therefore proposing that ` ExecutorJob ` gain
357
362
358
363
``` swift
359
364
extension ExecutorJob {
360
365
361
- /// Allocate a specified number of bytes of uninitialized memory.
362
- public func allocate (capacity : Int ) -> UnsafeMutableRawBufferPointer?
366
+ /// Obtain a stack-disciplined job-local allocator.
367
+ ///
368
+ /// If the job does not support allocation, this property will be
369
+ /// `nil`.
370
+ public var allocator: LocalAllocator? { get }
371
+
372
+ /// A job-local stack-disciplined allocator.
373
+ ///
374
+ /// This can be used to allocate additional data required by an
375
+ /// executor implementation; memory allocated in this manner will
376
+ /// be released automatically when the job is disposed of by the
377
+ /// runtime.
378
+ ///
379
+ /// N.B. Because this allocator is stack disciplined, explicitly
380
+ /// deallocating memory will also deallocate all memory allocated
381
+ /// after the block being deallocated.
382
+ struct LocalAllocator {
363
383
364
- /// Allocate uninitialized memory for a single instance of type `T` .
365
- public func allocate < T >( as : T. Type ) -> UnsafeMutablePointer <T> ?
384
+ /// Allocate a specified number of bytes of uninitialized memory .
385
+ public func allocate ( capacity : Int ) -> UnsafeMutableRawBufferPointer ?
366
386
367
- /// Allocate uninitialized memory for the specified number of
368
- /// instances of type `T`.
369
- public func allocate <T >(capacity : Int , as : T.Type )
370
- -> UnsafeMutableBufferPointer < T>?
387
+ /// Allocate uninitialized memory for a single instance of type `T`.
388
+ public func allocate <T >(as : T.Type ) -> UnsafeMutablePointer <T>?
371
389
372
- /// Deallocate previously allocated memory. Note that the task
373
- /// allocator is stack disciplined, so if you deallocate a block of
374
- /// memory, all memory allocated after that block is also deallocated.
375
- public func deallocate ( _ buffer : UnsafeMutableRawBufferPointer ? )
390
+ /// Allocate uninitialized memory for the specified number of
391
+ /// instances of type `T`.
392
+ public func allocate < T >( capacity : Int , as : T. Type )
393
+ -> UnsafeMutableBufferPointer < T >?
376
394
377
- /// Deallocate previously allocated memory. Note that the task
378
- /// allocator is stack disciplined, so if you deallocate a block of
379
- /// memory, all memory allocated after that block is also deallocated.
380
- public func deallocate < T > (_ pointer : UnsafeMutablePointer <T> ? )
395
+ /// Deallocate previously allocated memory. Note that the task
396
+ /// allocator is stack disciplined, so if you deallocate a block of
397
+ /// memory, all memory allocated after that block is also deallocated.
398
+ public func deallocate (_ buffer : UnsafeMutableRawBufferPointer ? )
381
399
382
- /// Deallocate previously allocated memory. Note that the task
383
- /// allocator is stack disciplined, so if you deallocate a block of
384
- /// memory, all memory allocated after that block is also deallocated.
385
- public func deallocate <T >(_ buffer : UnsafeMutableBufferPointer <T>? )
400
+ /// Deallocate previously allocated memory. Note that the task
401
+ /// allocator is stack disciplined, so if you deallocate a block of
402
+ /// memory, all memory allocated after that block is also deallocated.
403
+ public func deallocate <T >(_ pointer : UnsafeMutablePointer <T>? )
404
+
405
+ /// Deallocate previously allocated memory. Note that the task
406
+ /// allocator is stack disciplined, so if you deallocate a block of
407
+ /// memory, all memory allocated after that block is also deallocated.
408
+ public func deallocate <T >(_ buffer : UnsafeMutableBufferPointer <T>? )
409
+
410
+ }
386
411
387
412
}
388
413
```
389
414
390
- Calling these on a job not of kind ` JobKind.task ` is a fatal error.
415
+ In the current implementation, ` allocator ` will be ` nil ` for jobs
416
+ other than those of type ` ExecutorJob.Kind.task ` . This means that you
417
+ can write code like
418
+
419
+ ``` swift
420
+ if let chunk = job.allocator? .allocate (capacity : 1024 ) {
421
+
422
+ // Job supports allocation and `chunk` is a 1,024-byte buffer
423
+ ...
424
+
425
+ } else {
426
+
427
+ // Job does not support allocation
428
+
429
+ }
430
+ ```
391
431
392
432
### Embedded Swift
393
433
0 commit comments