Skip to content

Commit dc88bb9

Browse files
committed
[Maintenance] Add SerialExecutor for synchronously calling asynchronous jobs in order
1 parent 0296f4e commit dc88bb9

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

Sources/Utils/SerialExecutor.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// SerialExecutor.swift
3+
// AsyncBluetooth
4+
//
5+
// Created by luca on 20.08.2025.
6+
//
7+
8+
/// An executor that guarantees the async job order
9+
final class SerialExecutor: Sendable {
10+
private let continuation: AsyncStream<() async -> Void>.Continuation
11+
12+
init() {
13+
var c: AsyncStream<() async -> Void>.Continuation!
14+
let stream = AsyncStream<() async -> Void> { cont in
15+
c = cont
16+
}
17+
continuation = c
18+
19+
// Single task consuming jobs in FIFO order
20+
Task {
21+
for await job in stream {
22+
await job()
23+
}
24+
}
25+
}
26+
27+
func enqueue(_ job: @escaping () async -> Void) {
28+
continuation.yield(job) // sync, ordered
29+
}
30+
}

Sources/Utils/ThreadSafeArray.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Foundation
44

55
actor ThreadSafeArray<Element> {
66

7-
private var array: [Element]
7+
private(set) var array: [Element]
88

99
init(array: [Element] = []) {
1010
self.array = array

Tests/ThreadSafeArrayTest.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// ThreadSafeArrayTest.swift
3+
// AsyncBluetooth
4+
//
5+
// Created by luca on 20.08.2025.
6+
//
7+
8+
import Testing
9+
@testable import AsyncBluetooth
10+
11+
@Test
12+
func orderTest() async throws {
13+
let array: ThreadSafeArray<Int> = []
14+
let executor = SerialExecutor()
15+
for i in 1...1000 {
16+
executor.enqueue {
17+
await array.append(i)
18+
}
19+
}
20+
21+
try await Task.sleep(nanoseconds: UInt64(1e6))
22+
try await #require(array.array == Array(1...1000))
23+
}

0 commit comments

Comments
 (0)