mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
252 lines
8.1 KiB
C++
252 lines
8.1 KiB
C++
//===--- Executor.h - ABI structures for executors --------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Swift ABI describing executors.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_ABI_EXECUTOR_H
|
|
#define SWIFT_ABI_EXECUTOR_H
|
|
|
|
#include <inttypes.h>
|
|
#include "swift/ABI/Actor.h"
|
|
#include "swift/ABI/HeapObject.h"
|
|
#include "swift/Runtime/Casting.h"
|
|
|
|
namespace swift {
|
|
class AsyncContext;
|
|
class AsyncTask;
|
|
class DefaultActor;
|
|
class Job;
|
|
class SerialExecutorWitnessTable;
|
|
|
|
/// An unmanaged reference to an executor.
|
|
///
|
|
/// This type corresponds to the type Optional<Builtin.Executor> in
|
|
/// Swift. The representation of nil in Optional<Builtin.Executor>
|
|
/// aligns with what this type calls the generic executor, so the
|
|
/// notional subtype of this type which is never generic corresponds
|
|
/// to the type Builtin.Executor.
|
|
///
|
|
/// An executor reference is divided into two pieces:
|
|
///
|
|
/// - The identity, which is just a (potentially ObjC) object
|
|
/// reference; when this is null, the reference is generic.
|
|
/// Equality of executor references is based solely on equality
|
|
/// of identity.
|
|
///
|
|
/// - The implementation, which is an optional reference to a
|
|
/// witness table for the SerialExecutor protocol. When this
|
|
/// is null, but the identity is non-null, the reference is to
|
|
/// a default actor. The low bits of the implementation pointer
|
|
/// are reserved for the use of marking interesting properties
|
|
/// about the executor's implementation. The runtime masks these
|
|
/// bits off before accessing the witness table, so setting them
|
|
/// in the future should back-deploy as long as the witness table
|
|
/// reference is still present.
|
|
class ExecutorRef {
|
|
HeapObject *Identity; // Not necessarily Swift reference-countable
|
|
uintptr_t Implementation;
|
|
|
|
// We future-proof the ABI here by masking the low bits off the
|
|
// implementation pointer before using it as a witness table.
|
|
enum: uintptr_t {
|
|
WitnessTableMask = ~uintptr_t(alignof(void*) - 1)
|
|
};
|
|
|
|
constexpr ExecutorRef(HeapObject *identity, uintptr_t implementation)
|
|
: Identity(identity), Implementation(implementation) {}
|
|
|
|
public:
|
|
/// A generic execution environment. When running in a generic
|
|
/// environment, it's presumed to be okay to switch synchronously
|
|
/// to an actor. As an executor request, this represents a request
|
|
/// to drop whatever the current actor is.
|
|
constexpr static ExecutorRef generic() {
|
|
return ExecutorRef(nullptr, 0);
|
|
}
|
|
|
|
/// Given a pointer to a default actor, return an executor reference
|
|
/// for it.
|
|
static ExecutorRef forDefaultActor(DefaultActor *actor) {
|
|
assert(actor);
|
|
return ExecutorRef(actor, 0);
|
|
}
|
|
|
|
/// Given a pointer to a serial executor and its SerialExecutor
|
|
/// conformance, return an executor reference for it.
|
|
static ExecutorRef forOrdinary(HeapObject *identity,
|
|
const SerialExecutorWitnessTable *witnessTable) {
|
|
assert(identity);
|
|
assert(witnessTable);
|
|
return ExecutorRef(identity, reinterpret_cast<uintptr_t>(witnessTable));
|
|
}
|
|
|
|
HeapObject *getIdentity() const {
|
|
return Identity;
|
|
}
|
|
|
|
/// Is this the generic executor reference?
|
|
bool isGeneric() const {
|
|
return Identity == 0;
|
|
}
|
|
|
|
/// Is this a default-actor executor reference?
|
|
bool isDefaultActor() const {
|
|
return !isGeneric() && Implementation == 0;
|
|
}
|
|
DefaultActor *getDefaultActor() const {
|
|
assert(isDefaultActor());
|
|
return reinterpret_cast<DefaultActor*>(Identity);
|
|
}
|
|
|
|
const SerialExecutorWitnessTable *getSerialExecutorWitnessTable() const {
|
|
assert(!isGeneric() && !isDefaultActor());
|
|
auto table = Implementation & WitnessTableMask;
|
|
return reinterpret_cast<const SerialExecutorWitnessTable*>(table);
|
|
}
|
|
|
|
/// Do we have to do any work to start running as the requested
|
|
/// executor?
|
|
bool mustSwitchToRun(ExecutorRef newExecutor) const {
|
|
return Identity != newExecutor.Identity;
|
|
}
|
|
|
|
/// Is this executor the main executor?
|
|
bool isMainExecutor() const;
|
|
|
|
bool operator==(ExecutorRef other) const {
|
|
return Identity == other.Identity;
|
|
}
|
|
bool operator!=(ExecutorRef other) const {
|
|
return !(*this == other);
|
|
}
|
|
};
|
|
|
|
using JobInvokeFunction =
|
|
SWIFT_CC(swiftasync)
|
|
void (Job *);
|
|
|
|
using TaskContinuationFunction =
|
|
SWIFT_CC(swiftasync)
|
|
void (SWIFT_ASYNC_CONTEXT AsyncContext *);
|
|
|
|
using ThrowingTaskFutureWaitContinuationFunction =
|
|
SWIFT_CC(swiftasync)
|
|
void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *);
|
|
|
|
|
|
template <class AsyncSignature>
|
|
class AsyncFunctionPointer;
|
|
template <class AsyncSignature>
|
|
struct AsyncFunctionTypeImpl;
|
|
template <class AsyncSignature>
|
|
struct AsyncContinuationTypeImpl;
|
|
|
|
/// The abstract signature for an asynchronous function.
|
|
template <class Sig, bool HasErrorResult>
|
|
struct AsyncSignature;
|
|
|
|
template <class DirectResultTy, class... ArgTys, bool HasErrorResult>
|
|
struct AsyncSignature<DirectResultTy(ArgTys...), HasErrorResult> {
|
|
bool hasDirectResult = !std::is_same<DirectResultTy, void>::value;
|
|
using DirectResultType = DirectResultTy;
|
|
|
|
bool hasErrorResult = HasErrorResult;
|
|
|
|
using FunctionPointer = AsyncFunctionPointer<AsyncSignature>;
|
|
using FunctionType = typename AsyncFunctionTypeImpl<AsyncSignature>::type;
|
|
using ContinuationType = typename AsyncContinuationTypeImpl<AsyncSignature>::type;
|
|
};
|
|
|
|
/// A signature for a thin async function that takes no arguments
|
|
/// and returns no results.
|
|
using ThinNullaryAsyncSignature =
|
|
AsyncSignature<void(), false>;
|
|
|
|
/// A signature for a thick async function that takes no formal
|
|
/// arguments and returns no results.
|
|
using ThickNullaryAsyncSignature =
|
|
AsyncSignature<void(HeapObject*), false>;
|
|
|
|
template <class Signature>
|
|
struct AsyncFunctionTypeImpl;
|
|
|
|
template <class DirectResultTy, class... ArgTys, bool HasErrorResult>
|
|
struct AsyncFunctionTypeImpl<
|
|
AsyncSignature<DirectResultTy(ArgTys...), HasErrorResult>> {
|
|
|
|
using type = SWIFT_CC(swiftasync) void(SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
ArgTys...);
|
|
};
|
|
|
|
template <class Signature>
|
|
struct AsyncContinuationTypeImpl;
|
|
|
|
template <class DirectResultTy, class... ArgTys>
|
|
struct AsyncContinuationTypeImpl<
|
|
AsyncSignature<DirectResultTy(ArgTys...), /*throws=*/true>> {
|
|
|
|
using type = SWIFT_CC(swiftasync) void(SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
DirectResultTy,
|
|
SWIFT_CONTEXT void *);
|
|
};
|
|
|
|
template <class DirectResultTy, class... ArgTys>
|
|
struct AsyncContinuationTypeImpl<
|
|
AsyncSignature<DirectResultTy(ArgTys...), /*throws=*/false>> {
|
|
|
|
using type = SWIFT_CC(swiftasync) void(SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
DirectResultTy);
|
|
};
|
|
|
|
template <class... ArgTys>
|
|
struct AsyncContinuationTypeImpl<
|
|
AsyncSignature<void(ArgTys...), /*throws=*/true>> {
|
|
|
|
using type = SWIFT_CC(swiftasync) void(SWIFT_ASYNC_CONTEXT AsyncContext *,
|
|
SWIFT_CONTEXT SwiftError *);
|
|
};
|
|
|
|
template <class... ArgTys>
|
|
struct AsyncContinuationTypeImpl<
|
|
AsyncSignature<void(ArgTys...), /*throws=*/false>> {
|
|
|
|
using type = SWIFT_CC(swiftasync) void(SWIFT_ASYNC_CONTEXT AsyncContext *);
|
|
};
|
|
|
|
template <class Fn>
|
|
using AsyncFunctionType = typename AsyncFunctionTypeImpl<Fn>::type;
|
|
|
|
template <class Fn>
|
|
using AsyncContinuationType = typename AsyncContinuationTypeImpl<Fn>::type;
|
|
|
|
/// A "function pointer" for an async function.
|
|
///
|
|
/// Eventually, this will always be signed with the data key
|
|
/// using a type-specific discriminator.
|
|
template <class AsyncSignature>
|
|
class AsyncFunctionPointer {
|
|
public:
|
|
/// The function to run.
|
|
RelativeDirectPointer<AsyncFunctionType<AsyncSignature>,
|
|
/*nullable*/ false,
|
|
int32_t> Function;
|
|
|
|
/// The expected size of the context.
|
|
uint32_t ExpectedContextSize;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|