Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
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
2 changes: 1 addition & 1 deletion 2 Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ SWIFT_SDK_ID ?= wasm32-unknown-wasi
.PHONY: bootstrap
bootstrap:
npm ci
npx playwright install
npx playwright install chromium-headless-shell

.PHONY: unittest
unittest:
Expand Down
9 changes: 8 additions & 1 deletion 9 Sources/JavaScriptEventLoop/WebWorkerDedicatedExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,19 @@ public final class WebWorkerDedicatedExecutor: SerialExecutor {
private let underlying: WebWorkerTaskExecutor

/// - Parameters:
/// - stackSize: The stack size for each worker thread. Default is `nil` (use the platform default stack size).
/// - timeout: The maximum time to wait for all worker threads to be started. Default is 3 seconds.
/// - checkInterval: The interval to check if all worker threads are started. Default is 5 microseconds.
/// - Throws: An error if any worker thread fails to initialize within the timeout period.
public init(timeout: Duration = .seconds(3), checkInterval: Duration = .microseconds(5)) async throws {
/// - Note: The default stack size of wasi-libc is typically 128KB.
public init(
stackSize: Int? = nil,
timeout: Duration = .seconds(3),
checkInterval: Duration = .microseconds(5)
) async throws {
let underlying = try await WebWorkerTaskExecutor(
numberOfThreads: 1,
stackSize: stackSize,
timeout: timeout,
checkInterval: checkInterval
)
Expand Down
22 changes: 19 additions & 3 deletions 22 Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
self.workers = workers
}

func start(timeout: Duration, checkInterval: Duration) async throws {
func start(stackSize: Int?, timeout: Duration, checkInterval: Duration) async throws {
#if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded)
class Context: @unchecked Sendable {
let executor: WebWorkerTaskExecutor.Executor
Expand Down Expand Up @@ -375,9 +375,21 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
let unmanagedContext = Unmanaged.passRetained(context)
contexts.append(unmanagedContext)
let ptr = unmanagedContext.toOpaque()
var attr = pthread_attr_t()
pthread_attr_init(&attr)
// Set the stack size if specified.
if let stackSize {
let ret = pthread_attr_setstacksize(&attr, stackSize)
guard ret == 0 else {
let strerror = String(cString: strerror(ret))
throw SpawnError(
reason: "Failed to set stack size (\(stackSize)) for thread (\(ret): \(strerror))"
)
}
}
let ret = pthread_create(
nil,
nil,
&attr,
{ ptr in
// Cast to a optional pointer to absorb nullability variations between platforms.
let ptr: UnsafeMutableRawPointer? = ptr
Expand All @@ -390,6 +402,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
},
ptr
)
pthread_attr_destroy(&attr)
guard ret == 0 else {
let strerror = String(cString: strerror(ret))
throw SpawnError(reason: "Failed to create a thread (\(ret): \(strerror))")
Expand Down Expand Up @@ -467,16 +480,19 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
///
/// - Parameters:
/// - numberOfThreads: The number of Web Worker threads to spawn.
/// - stackSize: The stack size for each worker thread. Default is `nil` (use the platform default stack size).
/// - timeout: The maximum time to wait for all worker threads to be started. Default is 3 seconds.
/// - checkInterval: The interval to check if all worker threads are started. Default is 5 microseconds.
/// - Throws: An error if any worker thread fails to initialize within the timeout period.
/// - Note: The default stack size of wasi-libc is typically 128KB.
public init(
numberOfThreads: Int,
stackSize: Int? = nil,
timeout: Duration = .seconds(3),
checkInterval: Duration = .microseconds(5)
) async throws {
self.executor = Executor(numberOfThreads: numberOfThreads)
try await self.executor.start(timeout: timeout, checkInterval: checkInterval)
try await self.executor.start(stackSize: stackSize, timeout: timeout, checkInterval: checkInterval)
}

/// Terminates all worker threads managed by this executor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ final class WebWorkerTaskExecutorTests: XCTestCase {
executor.terminate()
}

func testThreadStackSize() async throws {
// Sanity check for stackSize parameter
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 3, stackSize: 512 * 1024)
executor.terminate()
}

func testTaskGroupRunOnDifferentThreads() async throws {
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 2)

Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.