Skip to content

Commit 43ab7e7

Browse files
Merge pull request #351 from swiftwasm/katei/unify-install-process
Unify the installGlobalExecutor process for JavaScriptEventLoop and WebWorkerTaskExecutor
2 parents d786374 + 01142d1 commit 43ab7e7

File tree

4 files changed

+16
-77
lines changed

4 files changed

+16
-77
lines changed

Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift

+12
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,18 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
207207
}
208208

209209
private func unsafeEnqueue(_ job: UnownedJob) {
210+
#if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded)
211+
guard swjs_get_worker_thread_id_cached() == SWJS_MAIN_THREAD_ID else {
212+
// Notify the main thread to execute the job when a job is
213+
// enqueued from a Web Worker thread but without an executor preference.
214+
// This is usually the case when hopping back to the main thread
215+
// at the end of a task.
216+
let jobBitPattern = unsafeBitCast(job, to: UInt.self)
217+
swjs_send_job_to_main_thread(jobBitPattern)
218+
return
219+
}
220+
// If the current thread is the main thread, do nothing special.
221+
#endif
210222
insertJobQueue(job: job)
211223
}
212224

Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift

+2-72
Original file line numberDiff line numberDiff line change
@@ -602,78 +602,8 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
602602
internal func dumpStats() {}
603603
#endif
604604

605-
// MARK: Global Executor hack
606-
607-
@MainActor private static var _mainThread: pthread_t?
608-
@MainActor private static var _swift_task_enqueueGlobal_hook_original: UnsafeMutableRawPointer?
609-
@MainActor private static var _swift_task_enqueueGlobalWithDelay_hook_original: UnsafeMutableRawPointer?
610-
@MainActor private static var _swift_task_enqueueGlobalWithDeadline_hook_original: UnsafeMutableRawPointer?
611-
612-
/// Installs a global executor that forwards jobs from Web Worker threads to the main thread.
613-
///
614-
/// This method sets up the necessary hooks to ensure proper task scheduling between
615-
/// the main thread and worker threads. It must be called once (typically at application
616-
/// startup) before using any `WebWorkerTaskExecutor` instances.
617-
///
618-
/// ## Example
619-
///
620-
/// ```swift
621-
/// // At application startup
622-
/// WebWorkerTaskExecutor.installGlobalExecutor()
623-
///
624-
/// // Later, create and use executor instances
625-
/// let executor = try await WebWorkerTaskExecutor(numberOfThreads: 4)
626-
/// ```
627-
///
628-
/// - Important: This method must be called from the main thread.
629-
public static func installGlobalExecutor() {
630-
MainActor.assumeIsolated {
631-
installGlobalExecutorIsolated()
632-
}
633-
}
634-
635-
@MainActor
636-
static func installGlobalExecutorIsolated() {
637-
#if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded)
638-
// Ensure this function is called only once.
639-
guard _mainThread == nil else { return }
640-
641-
_mainThread = pthread_self()
642-
assert(swjs_get_worker_thread_id() == -1, "\(#function) must be called on the main thread")
643-
644-
_swift_task_enqueueGlobal_hook_original = swift_task_enqueueGlobal_hook
645-
646-
typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original)
647-
-> Void
648-
let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, base in
649-
WebWorkerTaskExecutor.traceStatsIncrement(\.enqueueGlobal)
650-
// Enter this block only if the current Task has no executor preference.
651-
if pthread_equal(pthread_self(), WebWorkerTaskExecutor._mainThread) != 0 {
652-
// If the current thread is the main thread, delegate the job
653-
// execution to the original hook of JavaScriptEventLoop.
654-
let original = unsafeBitCast(
655-
WebWorkerTaskExecutor._swift_task_enqueueGlobal_hook_original,
656-
to: swift_task_enqueueGlobal_hook_Fn.self
657-
)
658-
original(job, base)
659-
} else {
660-
// Notify the main thread to execute the job when a job is
661-
// enqueued from a Web Worker thread but without an executor preference.
662-
// This is usually the case when hopping back to the main thread
663-
// at the end of a task.
664-
WebWorkerTaskExecutor.traceStatsIncrement(\.sendJobToMainThread)
665-
let jobBitPattern = unsafeBitCast(job, to: UInt.self)
666-
swjs_send_job_to_main_thread(jobBitPattern)
667-
}
668-
}
669-
swift_task_enqueueGlobal_hook = unsafeBitCast(
670-
swift_task_enqueueGlobal_hook_impl,
671-
to: UnsafeMutableRawPointer?.self
672-
)
673-
#else
674-
fatalError("Unsupported platform")
675-
#endif
676-
}
605+
@available(*, deprecated, message: "Not needed anymore, just use `JavaScriptEventLoop.installGlobalExecutor()`.")
606+
public static func installGlobalExecutor() {}
677607
}
678608

679609
/// Enqueue a job scheduled from a Web Worker thread to the main thread.

Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift

-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ import JavaScriptEventLoop
2727
func swift_javascriptkit_activate_js_executor_impl() {
2828
MainActor.assumeIsolated {
2929
JavaScriptEventLoop.installGlobalExecutor()
30-
#if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded)
31-
if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) {
32-
WebWorkerTaskExecutor.installGlobalExecutor()
33-
}
34-
#endif
3530
}
3631
}
3732

Sources/_CJavaScriptKit/include/_CJavaScriptKit.h

+2
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ IMPORT_JS_FUNCTION(swjs_get_worker_thread_id, int, (void))
326326

327327
IMPORT_JS_FUNCTION(swjs_create_object, JavaScriptObjectRef, (void))
328328

329+
#define SWJS_MAIN_THREAD_ID -1
330+
329331
int swjs_get_worker_thread_id_cached(void);
330332

331333
/// Requests sending a JavaScript object to another worker thread.

0 commit comments

Comments
 (0)