Skip to content

Use &_dispatch_main_q as the identity of the main actor. #37965

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/swift/ABI/Executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ class ExecutorRef {
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;
}
Expand Down Expand Up @@ -112,6 +121,9 @@ class ExecutorRef {
return Identity != newExecutor.Identity;
}

/// Is this executor the main executor?
bool isMainExecutor() const;

bool operator==(ExecutorRef other) const {
return Identity == other.Identity;
}
Expand Down
25 changes: 25 additions & 0 deletions include/swift/Basic/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,29 @@
#define SWIFT_POINTER_IS_4_BYTES 1
#endif

// Produce a string literal for the raw argument tokens.
#define SWIFT_STRINGIZE_RAW(TOK) #TOK

// Produce a string literal for the macro-expanded argument tokens.
#define SWIFT_STRINGIZE_EXPANDED(TOK) SWIFT_STRINGIZE_RAW(TOK)

#if defined(__USER_LABEL_PREFIX__)
#define SWIFT_SYMBOL_PREFIX_STRING \
SWIFT_STRINGIZE_EXPANDED(__USER_LABEL_PREFIX__)
#else
// Clang and GCC always define __USER_LABEL_PREFIX__, so this should
// only come up with MSVC, and Windows doesn't use a prefix.
#define SWIFT_SYMBOL_PREFIX_STRING ""
#endif

// An attribute to override the symbol name of a declaration.
// This does not compensate for platform symbol prefixes; for that,
// use SWIFT_ASM_LABEL_WITH_PREFIX.
//
// This only actually works on Clang or GCC; MSVC does not provide
// an attribute to change the asm label.
#define SWIFT_ASM_LABEL_RAW(STRING) __asm__(STRING)
#define SWIFT_ASM_LABEL_WITH_PREFIX(STRING) \
SWIFT_ASM_LABEL_RAW(SWIFT_SYMBOL_PREFIX_STRING STRING)

#endif // SWIFT_BASIC_COMPILER_H
1 change: 1 addition & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ LANGUAGE_FEATURE(BuiltinTaskGroup, 0, "TaskGroup builtins", true)
LANGUAGE_FEATURE(InheritActorContext, 0, "@_inheritActorContext attribute", true)
LANGUAGE_FEATURE(ImplicitSelfCapture, 0, "@_implicitSelfCapture attribute", true)
LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins", true)
LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin", true)

#undef LANGUAGE_FEATURE
8 changes: 8 additions & 0 deletions include/swift/Runtime/Concurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,10 @@ void swift_task_enqueueGlobalWithDelay(unsigned long long delay, Job *job);
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_task_enqueueMainExecutor(Job *job);

/// Enqueue the given job on the main executor.
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_task_enqueueOnDispatchQueue(Job *job, HeapObject *queue);

/// A hook to take over global enqueuing.
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobal_original)(Job *job);
SWIFT_EXPORT_FROM(swift_Concurrency)
Expand Down Expand Up @@ -680,6 +684,10 @@ AsyncTask *swift_task_getCurrent(void);
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
ExecutorRef swift_task_getCurrentExecutor(void);

/// Return the main-actor executor reference.
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
ExecutorRef swift_task_getMainExecutor(void);

SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
bool swift_task_isCurrentExecutor(ExecutorRef executor);

Expand Down
8 changes: 8 additions & 0 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,14 @@ FUNCTION(TaskGetCurrentExecutor,
ARGS(),
ATTRS(NoUnwind, ArgMemOnly))

// ExecutorRef swift_task_getMainExecutor();
FUNCTION(TaskGetMainExecutor,
swift_task_getMainExecutor, SwiftCC,
ConcurrencyAvailability,
RETURNS(SwiftExecutorTy),
ARGS(),
ATTRS(NoUnwind, ArgMemOnly))

// void swift_defaultActor_initialize(DefaultActor *actor);
FUNCTION(DefaultActorInitialize,
swift_defaultActor_initialize, SwiftCC,
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2768,6 +2768,10 @@ static bool usesFeatureBuiltinBuildExecutor(Decl *decl) {
return false;
}

static bool usesFeatureBuiltinBuildMainExecutor(Decl *decl) {
return false;
}

static bool usesFeatureBuiltinContinuation(Decl *decl) {
return false;
}
Expand Down
7 changes: 6 additions & 1 deletion lib/IRGen/GenConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ const LoadableTypeInfo &TypeConverter::getExecutorTypeInfo() {

void irgen::emitBuildMainActorExecutorRef(IRGenFunction &IGF,
Explosion &out) {
// FIXME
auto call = IGF.Builder.CreateCall(IGF.IGM.getTaskGetMainExecutorFn(),
{});
call->setDoesNotThrow();
call->setCallingConv(IGF.IGM.SwiftCC);

IGF.emitAllExtractValues(call, IGF.IGM.SwiftExecutorTy, out);
}

void irgen::emitBuildDefaultActorExecutorRef(IRGenFunction &IGF,
Expand Down
5 changes: 2 additions & 3 deletions stdlib/public/Concurrency/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,7 @@ static bool swift_task_isCurrentExecutorImpl(ExecutorRef executor) {
return currentTracking->getActiveExecutor() == executor;
}

return executor == _swift_task_getMainExecutor()
&& isExecutingOnMainThread();
return executor.isMainExecutor() && isExecutingOnMainThread();
}

/// Logging level for unexpected executors:
Expand Down Expand Up @@ -365,7 +364,7 @@ void swift::swift_task_reportUnexpectedExecutor(

const char *functionIsolation;
const char *whereExpected;
if (executor == _swift_task_getMainExecutor()) {
if (executor.isMainExecutor()) {
functionIsolation = "@MainActor function";
whereExpected = "the main thread";
} else {
Expand Down
9 changes: 0 additions & 9 deletions stdlib/public/Concurrency/Actor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,3 @@ public func _defaultActorDestroy(_ actor: AnyObject)
@_silgen_name("swift_task_enqueueMainExecutor")
@usableFromInline
internal func _enqueueOnMain(_ job: UnownedJob)

// Used by the concurrency runtime
@available(SwiftStdlib 5.5, *)
extension SerialExecutor {
@_silgen_name("_swift_task_getMainExecutor")
internal func _getMainExecutor() -> UnownedSerialExecutor {
return MainActor.shared.unownedExecutor
}
}
24 changes: 24 additions & 0 deletions stdlib/public/Concurrency/Executor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,27 @@ func _checkExpectedExecutor(_filenameStart: Builtin.RawPointer,
_reportUnexpectedExecutor(
_filenameStart, _filenameLength, _filenameIsASCII, _line, _executor)
}

@available(SwiftStdlib 5.5, *)
@_silgen_name("swift_task_enqueueOnDispatchQueue")
internal func _enqueueOnDispatchQueue(_ job: UnownedJob, queue: AnyObject)

/// Used by the runtime solely for the witness table it produces.
/// FIXME: figure out some way to achieve that which doesn't generate
/// all the other metadata
///
/// Expected to work for any primitive dispatch queue; note that this
/// means a dispatch_queue_t, which is not the same as DispatchQueue
/// on platforms where that is an instance of a wrapper class.
@available(SwiftStdlib 5.5, *)
internal class DispatchQueueShim: UnsafeSendable, SerialExecutor {
@inlinable
func enqueue(_ job: UnownedJob) {
_enqueueOnDispatchQueue(job, queue: self)
}

@inlinable
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
return UnownedSerialExecutor(ordinary: self)
}
}
20 changes: 18 additions & 2 deletions stdlib/public/Concurrency/GlobalExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,7 @@ static void swift_task_enqueueMainExecutorImpl(Job *job) {
// This is an inline function that compiles down to a pointer to a global.
auto mainQueue = dispatch_get_main_queue();

dispatchEnqueue(mainQueue, job, (dispatch_qos_class_t)priority,
DISPATCH_QUEUE_MAIN_EXECUTOR);
dispatchEnqueue(mainQueue, job, (dispatch_qos_class_t)priority, mainQueue);

#endif
}
Expand All @@ -404,5 +403,22 @@ void swift::swift_task_enqueueMainExecutor(Job *job) {
swift_task_enqueueMainExecutorImpl(job);
}

void swift::swift_task_enqueueOnDispatchQueue(Job *job,
HeapObject *_queue) {
JobPriority priority = job->getPriority();
auto queue = reinterpret_cast<dispatch_queue_t>(_queue);
dispatchEnqueue(queue, job, (dispatch_qos_class_t)priority, queue);
}

ExecutorRef swift::swift_task_getMainExecutor() {
return ExecutorRef::forOrdinary(
reinterpret_cast<HeapObject*>(&_dispatch_main_q),
_swift_task_getDispatchQueueSerialExecutorWitnessTable());
}

bool ExecutorRef::isMainExecutor() const {
return Identity == reinterpret_cast<HeapObject*>(&_dispatch_main_q);
}

#define OVERRIDE_GLOBAL_EXECUTOR COMPATIBILITY_OVERRIDE
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
16 changes: 12 additions & 4 deletions stdlib/public/Concurrency/MainActor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@ import Swift
/// A singleton actor whose executor is equivalent to the main
/// dispatch queue.
@available(SwiftStdlib 5.5, *)
@globalActor public final actor MainActor: SerialExecutor, GlobalActor {
@globalActor public final actor MainActor: GlobalActor {
public static let shared = MainActor()

@inlinable
public nonisolated var unownedExecutor: UnownedSerialExecutor {
return asUnownedSerialExecutor()
#if compiler(>=5.5) && $BuiltinBuildMainExecutor
return UnownedSerialExecutor(Builtin.buildMainActorExecutorRef())
#else
fatalError("Swift compiler is incompatible with this SDK version")
#endif
}

@inlinable
public nonisolated func asUnownedSerialExecutor() -> UnownedSerialExecutor {
return UnownedSerialExecutor(ordinary: self)
public static var sharedUnownedExecutor: UnownedSerialExecutor {
#if compiler(>=5.5) && $BuiltinBuildMainExecutor
return UnownedSerialExecutor(Builtin.buildMainActorExecutorRef())
#else
fatalError("Swift compiler is incompatible with this SDK version")
#endif
}

@inlinable
Expand Down
5 changes: 2 additions & 3 deletions stdlib/public/Concurrency/Task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,9 @@ static ExecutorRef executorForEnqueuedJob(Job *job) {
void *jobQueue = job->SchedulerPrivate[Job::DispatchQueueIndex];
if (jobQueue == DISPATCH_QUEUE_GLOBAL_EXECUTOR)
return ExecutorRef::generic();
else if (jobQueue == DISPATCH_QUEUE_MAIN_EXECUTOR)
return _swift_task_getMainExecutor();
else
swift_unreachable("jobQueue was not a known value.");
return ExecutorRef::forOrdinary(reinterpret_cast<HeapObject*>(jobQueue),
_swift_task_getDispatchQueueSerialExecutorWitnessTable());
}

static void jobInvoke(void *obj, void *unused, uint32_t flags) {
Expand Down
16 changes: 7 additions & 9 deletions stdlib/public/Concurrency/TaskPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,13 @@ void _swift_tsan_release(void *addr);
/// Special values used with DispatchQueueIndex to indicate the global and main
/// executors.
#define DISPATCH_QUEUE_GLOBAL_EXECUTOR (void *)1
#define DISPATCH_QUEUE_MAIN_EXECUTOR (void *)2

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
// FIXME: remove this and switch to a representation that uses
// _dispatch_main_q somehow
extern "C" SWIFT_CC(swift)
ExecutorRef _swift_task_getMainExecutor();
#pragma clang diagnostic pop

inline SerialExecutorWitnessTable *
_swift_task_getDispatchQueueSerialExecutorWitnessTable() {
extern SerialExecutorWitnessTable wtable
SWIFT_ASM_LABEL_WITH_PREFIX("$ss17DispatchQueueShimCScfsWP");
return &wtable;
}

// ==== ------------------------------------------------------------------------

Expand Down