Skip to content

Commit 9147b86

Browse files
committed
Add ExecutorJob.allocator and move allocation methods there.
The previous iteration would have required us to make calling the allocation methods a fatal error, and would have meant executors had to check explicitly for the `.task` job kind before using them. Instead, if we add a new `LocalAllocator` type, we can have an `allocator` property that is `nil` if the job doesn't support allocation, and a valid `LocalAllocator` otherwise.
1 parent d176b25 commit 9147b86

File tree

1 file changed

+68
-28
lines changed

1 file changed

+68
-28
lines changed

proposals/nnnn-custom-main-and-global-executors.md

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ struct ExecutorJob {
326326
...
327327

328328
/// Storage reserved for the executor
329-
var executorPrivate: (UInt, UInt)
329+
public var executorPrivate: (UInt, UInt)
330330

331331
/// Kinds of schedulable jobs.
332332
@frozen
@@ -344,50 +344,90 @@ struct ExecutorJob {
344344
}
345345

346346
/// What kind of job this is
347-
var kind: Kind
347+
public var kind: Kind
348348
...
349349
}
350350
```
351351

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
357362

358363
```swift
359364
extension ExecutorJob {
360365

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 {
363383

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?
366386

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>?
371389

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>?
376394

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?)
381399

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+
}
386411

387412
}
388413
```
389414

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+
```
391431

392432
### Embedded Swift
393433

0 commit comments

Comments
 (0)