mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1113 lines
43 KiB
C++
1113 lines
43 KiB
C++
//===--- Concurrency.h - Runtime interface for concurrency ------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The runtime interface for concurrency.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_RUNTIME_CONCURRENCY_H
|
|
#define SWIFT_RUNTIME_CONCURRENCY_H
|
|
|
|
#include "swift/ABI/AsyncLet.h"
|
|
#include "swift/ABI/Task.h"
|
|
#include "swift/ABI/TaskGroup.h"
|
|
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
|
|
|
// Does the runtime use a cooperative global executor?
|
|
#if defined(SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY)
|
|
#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 1
|
|
#else
|
|
#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 0
|
|
#endif
|
|
|
|
// Does the runtime use a task-thread model?
|
|
#if defined(SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY)
|
|
#define SWIFT_CONCURRENCY_TASK_TO_THREAD_MODEL 1
|
|
#else
|
|
#define SWIFT_CONCURRENCY_TASK_TO_THREAD_MODEL 0
|
|
#endif
|
|
|
|
namespace swift {
|
|
class DefaultActor;
|
|
class TaskOptionRecord;
|
|
|
|
struct SwiftError;
|
|
|
|
struct AsyncTaskAndContext {
|
|
AsyncTask *Task;
|
|
AsyncContext *InitialContext;
|
|
};
|
|
|
|
/// Create a task object.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
AsyncTaskAndContext swift_task_create(
|
|
size_t taskCreateFlags,
|
|
TaskOptionRecord *options,
|
|
const Metadata *futureResultType,
|
|
void *closureEntry, HeapObject *closureContext);
|
|
|
|
/// Caution: not all future-initializing functions actually throw, so
|
|
/// this signature may be incorrect.
|
|
using FutureAsyncSignature =
|
|
AsyncSignature<void(void*), /*throws*/ true>;
|
|
|
|
/// Create a task object.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
AsyncTaskAndContext swift_task_create_common(
|
|
size_t taskCreateFlags,
|
|
TaskOptionRecord *options,
|
|
const Metadata *futureResultType,
|
|
TaskContinuationFunction *function, void *closureContext,
|
|
size_t initialContextSize);
|
|
|
|
#if SWIFT_CONCURRENCY_TASK_TO_THREAD_MODEL
|
|
#define SWIFT_TASK_RUN_INLINE_INITIAL_CONTEXT_BYTES 4096
|
|
/// Begin an async context in the current sync context and run the indicated
|
|
/// closure in it.
|
|
///
|
|
/// This is only supported under the task-to-thread concurrency model and
|
|
/// relies on a synchronous implementation of task blocking in order to work.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swift)
|
|
void swift_task_run_inline(OpaqueValue *result, void *closureAFP,
|
|
OpaqueValue *closureContext,
|
|
const Metadata *futureResultType);
|
|
#endif
|
|
|
|
/// Allocate memory in a task.
|
|
///
|
|
/// This must be called synchronously with the task.
|
|
///
|
|
/// All allocations will be rounded to a multiple of MAX_ALIGNMENT.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void *swift_task_alloc(size_t size);
|
|
|
|
/// Deallocate memory in a task.
|
|
///
|
|
/// The pointer provided must be the last pointer allocated on
|
|
/// this task that has not yet been deallocated; that is, memory
|
|
/// must be allocated and deallocated in a strict stack discipline.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_dealloc(void *ptr);
|
|
|
|
/// Deallocate multiple memory allocations in a task.
|
|
///
|
|
/// The pointer provided must be a pointer previously allocated on
|
|
/// this task that has not yet been deallocated. All allocations up to and
|
|
/// including that allocation will be deallocated.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swift) void swift_task_dealloc_through(void *ptr);
|
|
|
|
/// Deallocate memory in a task.
|
|
///
|
|
/// The pointer provided must be the last pointer allocated on
|
|
/// this task that has not yet been deallocated; that is, memory
|
|
/// must be allocated and deallocated in a strict stack discipline.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_dealloc(void *ptr);
|
|
|
|
/// Allocate memory in a job.
|
|
///
|
|
/// All allocations will be rounded to a multiple of MAX_ALIGNMENT;
|
|
/// if the job does not support allocation, this will return NULL.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void *swift_job_allocate(Job *job, size_t size);
|
|
|
|
/// Deallocate memory in a job.
|
|
///
|
|
/// The pointer provided must be the last pointer allocated on
|
|
/// this task that has not yet been deallocated; that is, memory
|
|
/// must be allocated and deallocated in a strict stack discipline.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_job_deallocate(Job *job, void *ptr);
|
|
|
|
/// Cancel a task and all of its child tasks.
|
|
///
|
|
/// This can be called from any thread.
|
|
///
|
|
/// This has no effect if the task is already cancelled.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_cancel(AsyncTask *task);
|
|
|
|
/// Cancel all the child tasks that belong to the `group`.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_cancel_group_child_tasks(TaskGroup *group);
|
|
|
|
/// Escalate the priority of a task and all of its child tasks.
|
|
///
|
|
/// This can be called from any thread.
|
|
///
|
|
/// This has no effect if the task already has at least the given priority.
|
|
/// Returns the priority of the task.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
JobPriority
|
|
swift_task_escalate(AsyncTask *task, JobPriority newPriority);
|
|
|
|
// TODO: "async let wait" and "async let destroy" would be expressed
|
|
// similar to like TaskFutureWait;
|
|
|
|
/// Wait for a non-throwing future task to complete.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_task_future_wait(on task: _owned Builtin.NativeObject) async
|
|
/// -> Success
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_task_future_wait(OpaqueValue *,
|
|
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *,
|
|
TaskContinuationFunction *,
|
|
AsyncContext *);
|
|
|
|
/// Wait for a potentially-throwing future task to complete.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_task_future_wait_throwing(on task: _owned Builtin.NativeObject)
|
|
/// async throws -> Success
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_task_future_wait_throwing(
|
|
OpaqueValue *,
|
|
SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
AsyncTask *,
|
|
ThrowingTaskFutureWaitContinuationFunction *,
|
|
AsyncContext *);
|
|
|
|
/// Wait for a readyQueue of a Channel to become non empty.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_wait_next_throwing(
|
|
/// waitingTask: Builtin.NativeObject, // current task
|
|
/// group: Builtin.RawPointer
|
|
/// ) async throws -> T
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swiftasync)
|
|
void swift_taskGroup_wait_next_throwing(
|
|
OpaqueValue *resultPointer,
|
|
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
|
TaskGroup *group,
|
|
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
|
AsyncContext *callContext);
|
|
|
|
/// Initialize a `TaskGroup` in the passed `group` memory location.
|
|
/// The caller is responsible for retaining and managing the group's lifecycle.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_initialize(group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_initialize(TaskGroup *group, const Metadata *T);
|
|
|
|
/// Initialize a `TaskGroup` in the passed `group` memory location.
|
|
/// The caller is responsible for retaining and managing the group's lifecycle.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_initialize(flags: Int, group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_initializeWithFlags(size_t flags, TaskGroup *group, const Metadata *T);
|
|
|
|
/// Initialize a `TaskGroup` in the passed `group` memory location.
|
|
/// The caller is responsible for retaining and managing the group's lifecycle.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_initialize(flags: Int, group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_initializeWithOptions(size_t flags, TaskGroup *group, const Metadata *T, TaskOptionRecord *options);
|
|
|
|
/// Attach a child task to the parent task's task group record.
|
|
///
|
|
/// This function MUST be called from the AsyncTask running the task group.
|
|
///
|
|
/// Since the group (or rather, its record) is inserted in the parent task at
|
|
/// creation we do not need the parent task here, the group already is attached
|
|
/// to it.
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_attachChild(
|
|
/// group: Builtin.RawPointer,
|
|
/// child: Builtin.NativeObject
|
|
/// )
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_attachChild(TaskGroup *group, AsyncTask *child);
|
|
|
|
/// Its Swift signature is
|
|
///
|
|
/// This function MUST be called from the AsyncTask running the task group.
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_destroy(_ group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_destroy(TaskGroup *group);
|
|
|
|
/// Before starting a task group child task, inform the group that there is one
|
|
/// more 'pending' child to account for.
|
|
///
|
|
/// This function SHOULD be called from the AsyncTask running the task group,
|
|
/// however is generally thread-safe as it only works with the group status.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_addPending(
|
|
/// group: Builtin.RawPointer,
|
|
/// unconditionally: Bool
|
|
/// ) -> Bool
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_taskGroup_addPending(TaskGroup *group, bool unconditionally);
|
|
|
|
/// Cancel all tasks in the group.
|
|
/// This also prevents new tasks from being added.
|
|
///
|
|
/// This can be called from any thread.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_cancelAll(group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_taskGroup_cancelAll(TaskGroup *group);
|
|
|
|
/// Check ONLY if the group was explicitly cancelled, e.g. by `cancelAll`.
|
|
///
|
|
/// This check DOES NOT take into account the task in which the group is running
|
|
/// being cancelled or not.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_isCancelled(group: Builtin.RawPointer)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_taskGroup_isCancelled(TaskGroup *group);
|
|
|
|
/// Wait until all pending tasks from the task group have completed.
|
|
/// If this task group is accumulating results, this also discards all those results.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_waitAll(
|
|
/// waitingTask: Builtin.NativeObject, // current task
|
|
/// group: Builtin.RawPointer,
|
|
/// bodyError: Swift.Error?
|
|
/// ) async throws
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swiftasync)
|
|
void swift_taskGroup_waitAll(
|
|
OpaqueValue *resultPointer,
|
|
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
|
TaskGroup *group,
|
|
SwiftError *bodyError,
|
|
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
|
AsyncContext *callContext);
|
|
|
|
/// Check the readyQueue of a task group, return true if it has no pending tasks.
|
|
///
|
|
/// This can be called from any thread. Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_isEmpty(
|
|
/// _ group: Builtin.RawPointer
|
|
/// ) -> Bool
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_taskGroup_isEmpty(TaskGroup *group);
|
|
|
|
/// Enter the scope of an async let binding, creating a child task of the
|
|
/// current task to run the given function.
|
|
///
|
|
/// Behaves approximately like a Swift function with the following
|
|
/// signature, except the generic argument is in a different position:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_start<T>(
|
|
/// asyncLet: Builtin.RawPointer,
|
|
/// options: Builtin.RawPointer?,
|
|
/// operation: __owned @Sendable () async throws -> T,
|
|
/// resultBuffer: Builtin.RawPointer
|
|
/// )
|
|
/// \endcode
|
|
///
|
|
/// Previous versions of the concurrency runtime also provided a
|
|
/// \c swift_asyncLet_start which did not take a result buffer. This
|
|
/// function was never used by a released version of the compiler,
|
|
/// and it has been removed.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_asyncLet_begin(AsyncLet *alet,
|
|
TaskOptionRecord *options,
|
|
const Metadata *futureResultType,
|
|
void *closureEntryPoint, HeapObject *closureContext,
|
|
void *resultBuffer);
|
|
|
|
/// Get the value of a non-throwing async let, awaiting the result
|
|
/// if necessary.
|
|
///
|
|
/// This must be called from the parent task of the async let.
|
|
///
|
|
/// Behaves like a Swift async function with the signature:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_get(
|
|
/// _ asyncLet: Builtin.RawPointer,
|
|
/// _ resultBuffer: Builtin.RawPointer
|
|
/// ) async
|
|
/// \endcode
|
|
///
|
|
/// except that it uses the special calling convention in which the
|
|
/// continuation function, parent context, and child context are all
|
|
/// passed in separately rather than being stored in the child context.
|
|
/// The child async context has a fixed size of 5 * sizeof(void*).
|
|
///
|
|
/// \c resultBuffer must be the same result buffer that was passed to
|
|
/// swift_asyncLet_begin. After asynchronous return, it is guaranteed
|
|
/// to be initialized.
|
|
///
|
|
/// Previous versions of the concurrency runtime also provided a
|
|
/// \c swift_asyncLet_wait which was meant to be paired with
|
|
/// \c swift_asyncLet_start. This function was never used by
|
|
/// a released version of the compiler, and it has been removed.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_asyncLet_get(SWIFT_ASYNC_CONTEXT AsyncContext *parentContext,
|
|
AsyncLet *alet,
|
|
void *resultBuffer,
|
|
TaskContinuationFunction *continuation,
|
|
AsyncContext *childContext);
|
|
|
|
/// Get the value of a throwing async let, awaiting the result if necessary.
|
|
///
|
|
/// This must be called from the parent task of the async let.
|
|
///
|
|
/// Behaves like a Swift async function with the signature:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_get_throwing(
|
|
/// _ asyncLet: Builtin.RawPointer,
|
|
/// _ resultBuffer: Builtin.RawPointer
|
|
/// ) async throws
|
|
/// \endcode
|
|
///
|
|
/// except that it uses the special calling convention in which the
|
|
/// continuation function, parent context, and child context are all
|
|
/// passed in separately rather than being stored in the child context.
|
|
/// The child async context has a fixed size of 5 * sizeof(void*).
|
|
///
|
|
/// \c resultBuffer must be the same result buffer that was passed to
|
|
/// swift_asyncLet_begin. After asynchronous return, it is guaranteed
|
|
/// to be initialized unless the operation throws by passing an error
|
|
/// to the continuation function.
|
|
///
|
|
/// Previous versions of the concurrency runtime also provided a
|
|
/// \c swift_asyncLet_wait_throwing which was meant to be paired with
|
|
/// \c swift_asyncLet_start. This function was never used by
|
|
/// a released version of the compiler, and it has been removed.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_asyncLet_get_throwing(SWIFT_ASYNC_CONTEXT AsyncContext *parentContext,
|
|
AsyncLet *alet,
|
|
void *resultBuffer,
|
|
ThrowingTaskFutureWaitContinuationFunction *
|
|
continuation,
|
|
AsyncContext *childContext);
|
|
|
|
/// Exit the scope of an async let binding that was created with
|
|
/// swift_asyncLet_begin. If the child task is still running, it is
|
|
/// cancelled, and the current task is suspended to await its completion.
|
|
///
|
|
/// This must be called from the parent task of the async let.
|
|
///
|
|
/// Behaves like a Swift async function with the signature:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_finish(_ asyncLet: Builtin.RawPointer,
|
|
/// _ resultBuffer: Builtin.RawPointer) async
|
|
/// \endcode
|
|
///
|
|
/// except that it uses the special calling convention in which the
|
|
/// continuation function, parent context, and child context are all
|
|
/// passed in separately rather than being stored in the child context.
|
|
/// The child async context has a fixed size of 5 * sizeof(void*).
|
|
///
|
|
/// \c resultBuffer must be the same result buffer that was passed to
|
|
/// swift_asyncLet_begin.
|
|
///
|
|
/// Prior to asynchronous return, the value in the result buffer is
|
|
/// destroyed (if present) and any memory initially allocated for the
|
|
/// task is deallocated. Because swift_asyncLet_begin potentially
|
|
/// allocates memory on the parent task's task allocator, the call to
|
|
/// this function must be properly paired with the begin.
|
|
///
|
|
/// The async let is invalid after this call and cannot be used again.
|
|
///
|
|
/// Previous versions of the concurrency runtime also provided a
|
|
/// \c swift_asyncLet_end which was not asynchronous and was meant
|
|
/// to be paired with \c swift_asyncLet_start. This function was never
|
|
/// used by a released version of the compiler, and it has been removed.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_asyncLet_finish(SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
AsyncLet *,
|
|
void *,
|
|
TaskContinuationFunction *,
|
|
AsyncContext *);
|
|
|
|
/// Get the value of a non-throwing async let binding that was created
|
|
/// with \c swift_asyncLet_begin, awaiting the task's completion if
|
|
/// necessary, and then destroy the task and the binding.
|
|
///
|
|
/// This must be called from the parent task of the async let.
|
|
///
|
|
/// Behaves like a Swift async function with the signature:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_get(
|
|
/// _ asyncLet: Builtin.RawPointer,
|
|
/// _ resultBuffer: Builtin.RawPointer
|
|
/// ) async
|
|
/// \endcode
|
|
///
|
|
/// except that it uses the special calling convention in which the
|
|
/// continuation function, parent context, and child context are all
|
|
/// passed in separately rather than being stored in the child context.
|
|
/// The child async context has a fixed size of 5 * sizeof(void*).
|
|
///
|
|
/// \c resultBuffer must be the same result buffer that was passed to
|
|
/// swift_asyncLet_begin. After asynchronous return, this is guaranteed
|
|
/// to be initialized.
|
|
///
|
|
/// The async let is invalid after this call and cannot be used again.
|
|
/// Any memory initially allocated for the task is deallocated. Because
|
|
/// \c swift_asyncLet_begin potentially allocates memory on the parent
|
|
/// task's task allocator, the call to this function must be properly
|
|
/// paired with the begin.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_asyncLet_consume(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
|
AsyncLet *alet,
|
|
void *resultBuffer,
|
|
TaskContinuationFunction *continuation,
|
|
AsyncContext *callContext);
|
|
|
|
/// Get the value of a throwing async let binding that was created
|
|
/// with \c swift_asyncLet_begin, awaiting the task's completion if
|
|
/// necessary, and then destroy the task and the binding.
|
|
///
|
|
/// This must be called from the parent task of the async let.
|
|
///
|
|
/// Behaves like a Swift async function with the signature:
|
|
///
|
|
/// \code
|
|
/// func swift_asyncLet_get_throwing(
|
|
/// _ asyncLet: Builtin.RawPointer,
|
|
/// _ resultBuffer: Builtin.RawPointer
|
|
/// ) async throws
|
|
/// \endcode
|
|
///
|
|
/// except that it uses the special calling convention in which the
|
|
/// continuation function, parent context, and child context are all
|
|
/// passed in separately rather than being stored in the child context.
|
|
/// The child async context has a fixed size of 5 * sizeof(void*).
|
|
///
|
|
/// \c resultBuffer must be the same result buffer that was passed to
|
|
/// swift_asyncLet_begin. After asynchronous return, it is guaranteed
|
|
/// to be initialized unless the operation throws by passing an error
|
|
/// to the continuation function.
|
|
///
|
|
/// The async let is invalid after this call and cannot be used again.
|
|
/// Any memory initially allocated for the task is deallocated. Because
|
|
/// \c swift_asyncLet_begin potentially allocates memory on the parent
|
|
/// task's task allocator, the call to this function must be properly
|
|
/// paired with the begin.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_asyncLet_consume_throwing(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
|
AsyncLet *alet,
|
|
void *resultBuffer,
|
|
ThrowingTaskFutureWaitContinuationFunction *
|
|
continuation,
|
|
AsyncContext *callContext);
|
|
|
|
/// Returns true if the currently executing AsyncTask has a
|
|
/// 'TaskGroupTaskStatusRecord' present.
|
|
///
|
|
/// This can be called from any thread.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_taskGroup_hasTaskGroupRecord()
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_taskGroup_hasTaskGroupRecord(); // FIXME: not used? we have swift_task_hasTaskGroupStatusRecord
|
|
|
|
/// Signifies whether the current task is in the middle of executing the
|
|
/// operation block of a `with(Throwing)TaskGroup(...) { <operation> }`.
|
|
///
|
|
/// Task local values must use un-structured allocation for values bound in this
|
|
/// scope, as they may be referred to by `group.spawn`-ed tasks and therefore
|
|
/// out-life the scope of a task-local value binding.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_hasTaskGroupStatusRecord();
|
|
|
|
/// Push an executor preference onto the current task.
|
|
/// The pushed reference does not keep the executor alive, and it is the
|
|
/// responsibility of the end user to ensure that the task executor reference
|
|
/// remains valid throughout the time it may be used by any task.
|
|
///
|
|
/// Runtime availability: Swift 9999.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
TaskExecutorPreferenceStatusRecord*
|
|
swift_task_pushTaskExecutorPreference(TaskExecutorRef executor);
|
|
|
|
/// Remove a single task executor preference record from the current task.
|
|
///
|
|
/// Must be passed the record intended to be removed (returned by
|
|
/// `swift_task_pushTaskExecutorPreference`).
|
|
///
|
|
/// Failure to remove the expected record should result in a runtime crash as it
|
|
/// signals a bug in record handling by the concurrency library -- a record push
|
|
/// must always be paired with a record pop.
|
|
///
|
|
/// Runtime availability: Swift 6.0
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_popTaskExecutorPreference(TaskExecutorPreferenceStatusRecord* record);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
size_t swift_task_getJobFlags(AsyncTask* task);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_isCancelled(AsyncTask* task);
|
|
|
|
/// Returns the current priority of the task which is >= base priority of the
|
|
/// task. This function does not exist in the base ABI of this library and must
|
|
/// be deployment limited
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
JobPriority
|
|
swift_task_currentPriority(AsyncTask *task);
|
|
|
|
/// Returns the base priority of the task. This function does not exist in the
|
|
/// base ABI of this library and must be deployment limited.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
JobPriority
|
|
swift_task_basePriority(AsyncTask *task);
|
|
|
|
/// Returns the priority of the job.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
JobPriority
|
|
swift_concurrency_jobPriority(Job *job);
|
|
|
|
/// Create and add an cancellation record to the task.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
CancellationNotificationStatusRecord*
|
|
swift_task_addCancellationHandler(
|
|
CancellationNotificationStatusRecord::FunctionType handler,
|
|
void *handlerContext);
|
|
|
|
/// Remove the passed cancellation record from the task.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_removeCancellationHandler(
|
|
CancellationNotificationStatusRecord *record);
|
|
|
|
/// Create and add an priority escalation record to the task.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
EscalationNotificationStatusRecord*
|
|
swift_task_addPriorityEscalationHandler(
|
|
EscalationNotificationStatusRecord::FunctionType handler,
|
|
void *handlerContext);
|
|
|
|
/// Remove the passed priority escalation record from the task.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_removePriorityEscalationHandler(
|
|
EscalationNotificationStatusRecord *record);
|
|
|
|
/// Create a NullaryContinuationJob from a continuation.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
NullaryContinuationJob*
|
|
swift_task_createNullaryContinuationJob(
|
|
size_t priority,
|
|
AsyncTask *continuation);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swift)
|
|
void swift_task_deinitOnExecutor(void *object, DeinitWorkFunction *work,
|
|
SerialExecutorRef newExecutor, size_t flags);
|
|
|
|
/// Report error about attempting to bind a task-local value from an illegal context.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_reportIllegalTaskLocalBindingWithinWithTaskGroup(
|
|
const unsigned char *file, uintptr_t fileLength,
|
|
bool fileIsASCII, uintptr_t line);
|
|
|
|
/// Get a task local value from either the current task, or fallback task-local
|
|
/// storage.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func _taskLocalValueGet<Key>(
|
|
/// keyType: Any.Type /*Key.Type*/
|
|
/// ) -> UnsafeMutableRawPointer? where Key: TaskLocalKey
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
OpaqueValue*
|
|
swift_task_localValueGet(const HeapObject *key);
|
|
|
|
/// Bind a task local key to a value in the context of either the current
|
|
/// AsyncTask if present, or in the thread-local fallback context if no task
|
|
/// available.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// public func _taskLocalValuePush<Value>(
|
|
/// keyType: Any.Type/*Key.Type*/,
|
|
/// value: __owned Value
|
|
/// )
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_localValuePush(const HeapObject *key,
|
|
/* +1 */ OpaqueValue *value,
|
|
const Metadata *valueType);
|
|
|
|
/// Pop a single task local binding from the binding stack of the current task,
|
|
/// or the fallback thread-local storage if no task is available.
|
|
///
|
|
/// This operation must be paired up with a preceding "push" operation, as otherwise
|
|
/// it may attempt to "pop" off an empty value stuck which will lead to a crash.
|
|
///
|
|
/// The Swift surface API ensures proper pairing of push and pop operations.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// public func _taskLocalValuePop()
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_localValuePop();
|
|
|
|
/// Copy all task locals from the current context to the target task.
|
|
///
|
|
/// Its Swift signature is
|
|
///
|
|
/// \code
|
|
/// func swift_task_localsCopyTo<Key>(AsyncTask* task)
|
|
/// \endcode
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_localsCopyTo(AsyncTask* target);
|
|
|
|
/// Switch the current task to a new executor if we aren't already
|
|
/// running on a compatible executor.
|
|
///
|
|
/// The resumption function pointer and continuation should be set
|
|
/// appropriately in the task.
|
|
///
|
|
/// Generally the compiler should inline a fast-path compatible-executor
|
|
/// check to avoid doing the suspension work. This function should
|
|
/// generally be tail-called, as it may continue executing the task
|
|
/// synchronously if possible.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_task_switch(SWIFT_ASYNC_CONTEXT AsyncContext *resumeToContext,
|
|
TaskContinuationFunction *resumeFunction,
|
|
SerialExecutorRef newExecutor);
|
|
|
|
/// Mark a task for enqueue on a new executor and then enqueue it.
|
|
///
|
|
/// The resumption function pointer and continuation should be set
|
|
/// appropriately in the task.
|
|
///
|
|
/// Generally you should call swift_task_switch to switch execution
|
|
/// synchronously when possible.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void
|
|
swift_task_enqueueTaskOnExecutor(AsyncTask *task, SerialExecutorRef executor);
|
|
|
|
/// Enqueue the given job to run asynchronously on the given executor.
|
|
///
|
|
/// The resumption function pointer and continuation should be set
|
|
/// appropriately in the task.
|
|
///
|
|
/// Generally you should call swift_task_switch to switch execution
|
|
/// synchronously when possible.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueue(Job *job, SerialExecutorRef executor);
|
|
|
|
/// Enqueue the given job to run asynchronously on the global
|
|
/// execution pool.
|
|
///
|
|
/// The resumption function pointer and continuation should be set
|
|
/// appropriately in the task.
|
|
///
|
|
/// Generally you should call swift_task_switch to switch execution
|
|
/// synchronously when possible.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueueGlobal(Job *job);
|
|
|
|
/// Invoke an executor's `checkIsolated` implementation;
|
|
/// It will crash if the current executor is NOT the passed executor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_checkIsolated(SerialExecutorRef executor);
|
|
|
|
/// Invoke a Swift executor's `checkIsolated` implementation; returns
|
|
/// `true` if it invoked the Swift implementation, `false` otherwise.
|
|
/// Executors will want to call this from their `swift_task_checkIsolatedImpl`
|
|
/// implementation.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_invokeSwiftCheckIsolated(SerialExecutorRef executor);
|
|
|
|
/// Invoke an executor's `isIsolatingCurrentContext` implementation;
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
int8_t swift_task_isIsolatingCurrentContext(SerialExecutorRef executor);
|
|
|
|
/// Invoke a Swift executor's `isIsolatingCurrentContext` implementation; returns
|
|
/// `true` if it invoked the Swift implementation, `false` otherwise.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
int8_t swift_task_invokeSwiftIsIsolatingCurrentContext(SerialExecutorRef executor);
|
|
|
|
/// A count in nanoseconds.
|
|
using JobDelay = unsigned long long;
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueueGlobalWithDelay(JobDelay delay, Job *job);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueueGlobalWithDeadline(long long sec, long long nsec,
|
|
long long tsec, long long tnsec, int clock, Job *job);
|
|
|
|
/// Enqueue the given job on the main executor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueueMainExecutor(Job *job);
|
|
|
|
/// WARNING: This method is expected to CRASH when caller is not on the
|
|
/// expected executor.
|
|
///
|
|
/// Return true if the caller is running in a Task on the passed Executor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_isOnExecutor(
|
|
HeapObject * executor,
|
|
const Metadata *selfType,
|
|
const SerialExecutorWitnessTable *wtable);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_executor_isComplexEquality(SerialExecutorRef ref);
|
|
|
|
/// Return the 64bit TaskID (if the job is an AsyncTask),
|
|
/// or the 32bits of the job Id otherwise.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
uint64_t swift_task_getJobTaskId(Job *job);
|
|
|
|
#if SWIFT_CONCURRENCY_ENABLE_DISPATCH
|
|
|
|
/// Enqueue the given job on the main executor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_enqueueOnDispatchQueue(Job *job, HeapObject *queue);
|
|
|
|
#endif
|
|
|
|
// Declare all the hooks
|
|
#define SWIFT_CONCURRENCY_HOOK(returnType, name, ...) \
|
|
typedef SWIFT_CC(swift) returnType (*name##_original)(__VA_ARGS__); \
|
|
typedef SWIFT_CC(swift) returnType \
|
|
(*name##_hook_t)(__VA_ARGS__, name##_original original); \
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
|
|
|
|
#define SWIFT_CONCURRENCY_HOOK0(returnType, name) \
|
|
typedef SWIFT_CC(swift) returnType (*name##_original)(); \
|
|
typedef SWIFT_CC(swift) returnType \
|
|
(*name##_hook_t)(name##_original original); \
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
|
|
|
|
#include "ConcurrencyHooks.def"
|
|
|
|
// This is a compatibility hook, *not* a concurrency hook
|
|
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_original)();
|
|
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_override)(
|
|
swift_task_asyncMainDrainQueue_original original);
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_hook)(
|
|
swift_task_asyncMainDrainQueue_original original,
|
|
swift_task_asyncMainDrainQueue_override compatOverride);
|
|
|
|
/// Initialize the runtime storage for a default actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_defaultActor_initialize(DefaultActor *actor);
|
|
|
|
/// Destroy the runtime storage for a default actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_defaultActor_destroy(DefaultActor *actor);
|
|
|
|
/// Deallocate an instance of a default actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_defaultActor_deallocate(DefaultActor *actor);
|
|
|
|
/// Deallocate an instance of what might be a default actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_defaultActor_deallocateResilient(HeapObject *actor);
|
|
|
|
/// Initialize the runtime storage for a non-default distributed actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_nonDefaultDistributedActor_initialize(NonDefaultDistributedActor *actor);
|
|
|
|
/// Create and initialize the runtime storage for a distributed remote actor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
OpaqueValue*
|
|
swift_distributedActor_remote_initialize(const Metadata *actorType);
|
|
|
|
/// Enqueue a job on the default actor implementation.
|
|
///
|
|
/// The job must be ready to run. Notably, if it's a task, that
|
|
/// means that the resumption function and context should have been
|
|
/// set appropriately.
|
|
///
|
|
/// Jobs are assumed to be "self-consuming": once it starts running,
|
|
/// the job memory is invalidated and the executor should not access it
|
|
/// again.
|
|
///
|
|
/// Jobs are generally expected to keep the actor alive during their
|
|
/// execution.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_defaultActor_enqueue(Job *job, DefaultActor *actor);
|
|
|
|
/// Check if the actor is a distributed 'remote' actor instance.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_distributed_actor_is_remote(HeapObject *actor);
|
|
|
|
/// Do a primitive suspension of the current task, as if part of
|
|
/// a continuation, although this does not provide any of the
|
|
/// higher-level continuation semantics. The current task is returned;
|
|
/// its ResumeFunction and ResumeContext will need to be initialized,
|
|
/// and then it will need to be enqueued or run as a job later.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
AsyncTask *swift_task_suspend();
|
|
|
|
/// Prepare a continuation in the current task.
|
|
///
|
|
/// The caller should initialize the Parent, ResumeParent,
|
|
/// and NormalResult fields. This function will initialize the other
|
|
/// fields with appropriate defaults; the caller may then overwrite
|
|
/// them if desired.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
AsyncTask *swift_continuation_init(ContinuationAsyncContext *context,
|
|
AsyncContinuationFlags flags);
|
|
|
|
/// Await an initialized continuation.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
|
|
void swift_continuation_await(ContinuationAsyncContext *continuationContext);
|
|
|
|
/// Resume a task from a non-throwing continuation, given a normal
|
|
/// result which has already been stored into the continuation.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_continuation_resume(AsyncTask *continuation);
|
|
|
|
/// Resume a task from a potentially-throwing continuation, given a
|
|
/// normal result which has already been stored into the continuation.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_continuation_throwingResume(AsyncTask *continuation);
|
|
|
|
/// Resume a task from a potentially-throwing continuation by throwing
|
|
/// an error.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_continuation_throwingResumeWithError(AsyncTask *continuation,
|
|
/* +1 */ SwiftError *error);
|
|
|
|
/// SPI helper to log a misuse of a `CheckedContinuation` to the appropriate places in the OS.
|
|
extern "C" SWIFT_CC(swift)
|
|
void swift_continuation_logFailedCheck(const char *message);
|
|
|
|
/// Drain the queue
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_asyncMainDrainQueue [[noreturn]]();
|
|
|
|
/// Drain the global executor. This does the same as the above, but
|
|
/// swift_task_asyncMainDrainQueue() is a compatibility override point,
|
|
/// whereas this function has a concurrency hook. The default
|
|
/// swift_task_asyncMainDrainQueue() implementation just calls this function.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_drainGlobalExecutor [[noreturn]]();
|
|
|
|
/// Establish that the current thread is running as the given
|
|
/// executor, then run a job.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_job_run(Job *job, SerialExecutorRef executor);
|
|
|
|
/// Establish that the current thread is running as the given
|
|
/// executor, then run a job.
|
|
///
|
|
/// Runtime availability: Swift 6.0
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_job_run_on_task_executor(Job *job, TaskExecutorRef executor);
|
|
|
|
/// Establish that the current thread is running as the given
|
|
/// executor, then run a job.
|
|
///
|
|
/// Runtime availability: Swift 6.0
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_job_run_on_serial_and_task_executor(Job *job,
|
|
SerialExecutorRef serialExecutor,
|
|
TaskExecutorRef taskExecutor);
|
|
|
|
/// Return the current thread's active task reference.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
AsyncTask *swift_task_getCurrent(void);
|
|
|
|
/// Return the current thread's active executor reference.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
SerialExecutorRef swift_task_getCurrentExecutor(void);
|
|
|
|
/// Return the main-actor executor reference.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
SerialExecutorRef swift_task_getMainExecutor(void);
|
|
|
|
/// Test if an executor is the main executor.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_isMainExecutor(SerialExecutorRef executor);
|
|
|
|
/// Return the preferred task executor of the current task,
|
|
/// or ``TaskExecutorRef::undefined()`` if no preference.
|
|
///
|
|
/// A stored preference may be `undefined` explicitly,
|
|
/// which is semantically equivalent to having no preference.
|
|
///
|
|
/// The returned reference must be treated carefully,
|
|
/// because it is *unmanaged*, meaning that the fact
|
|
/// that the task "has" this preference does not imply its lifetime.
|
|
///
|
|
/// Developers who use task executor preference MUST guarantee
|
|
/// their lifetime exceeds any use of such executor. For example,
|
|
/// they should be created as "forever" alive singletons, or otherwise
|
|
/// guarantee their lifetime extends beyond all potential uses of them by tasks.
|
|
///
|
|
/// Runtime availability: Swift 9999
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
TaskExecutorRef swift_task_getPreferredTaskExecutor(void);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
bool swift_task_isCurrentExecutor(SerialExecutorRef executor);
|
|
|
|
/// This is an options enum that is used to pass flags to
|
|
/// swift_task_isCurrentExecutorWithFlags. It is meant to be a flexible toggle.
|
|
///
|
|
/// Since this is an options enum, so all values should be powers of 2.
|
|
///
|
|
/// NOTE: We are purposely leaving this as a uint64_t so that on all platforms
|
|
/// this could be a pointer to a different enum instance if we need it to be.
|
|
enum swift_task_is_current_executor_flag : uint64_t {
|
|
/// We aren't passing any flags.
|
|
/// Effectively this is a backwards compatible mode.
|
|
None = 0x0,
|
|
|
|
/// This is not used today, but is just future ABI reservation.
|
|
///
|
|
/// The intention is that we may want the ability to tell future versions of
|
|
/// the runtime that this uint64_t is actually a pointer that it should
|
|
/// dereference and then have further extended behavior controlled by a
|
|
/// different enum. By placing this here, we ensure that we will have a tagged
|
|
/// pointer compatible flag for this purpose.
|
|
TaggedPointer = 0x1,
|
|
|
|
/// This is not used today, but is just future ABI reservation.
|
|
///
|
|
/// \see swift_task_is_current_executor_flag::TaggedPointer
|
|
TaggedPointer2 = 0x2,
|
|
|
|
/// This is not used today, but is just future ABI reservation.
|
|
///
|
|
/// \see swift_task_is_current_executor_flag::TaggedPointer
|
|
TaggedPointer3 = 0x4,
|
|
|
|
/// The routine should assert on failure.
|
|
Assert = 0x8,
|
|
|
|
/// The routine MUST NOT assert on failure.
|
|
/// Even at the cost of not calling 'checkIsolated' if it is available.
|
|
MustNotAssert = 0x10,
|
|
};
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
SWIFT_CC(swift)
|
|
bool swift_task_isCurrentExecutorWithFlags(
|
|
SerialExecutorRef executor, swift_task_is_current_executor_flag flags);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_reportUnexpectedExecutor(
|
|
const unsigned char *file, uintptr_t fileLength, bool fileIsASCII,
|
|
uintptr_t line, SerialExecutorRef executor);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
JobPriority swift_task_getCurrentThreadPriority(void);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
const char *swift_task_getCurrentTaskName(void);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_startOnMainActor(AsyncTask* job);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_immediate(AsyncTask* job, SerialExecutorRef targetExecutor);
|
|
|
|
/// Donate this thread to the global executor until either the
|
|
/// given condition returns true or we've run out of cooperative
|
|
/// tasks to run.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void*),
|
|
void *context);
|
|
|
|
enum swift_clock_id : int {
|
|
swift_clock_id_continuous = 1,
|
|
swift_clock_id_suspending = 2,
|
|
swift_clock_id_wall = 3
|
|
};
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_get_time(long long *seconds,
|
|
long long *nanoseconds,
|
|
swift_clock_id clock_id);
|
|
|
|
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
|
void swift_get_clock_res(long long *seconds,
|
|
long long *nanoseconds,
|
|
swift_clock_id clock_id);
|
|
|
|
#ifdef __APPLE__
|
|
/// A magic symbol whose address is the mask to apply to a frame pointer to
|
|
/// signal that it is an async frame. Do not try to read the actual value of
|
|
/// this global, it will crash.
|
|
///
|
|
/// On ARM64_32, the address is only 32 bits, and therefore this value covers
|
|
/// the top 32 bits of the in-memory frame pointer. On other 32-bit platforms,
|
|
/// the bit is not used and the address is always 0.
|
|
SWIFT_EXPORT_FROM(swift_Concurrency)
|
|
struct { char c; } swift_async_extendedFramePointerFlags;
|
|
#endif
|
|
|
|
}
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
#endif
|