File tree Expand file tree Collapse file tree 3 files changed +54
-1
lines changed
Expand file tree Collapse file tree 3 files changed +54
-1
lines changed Original file line number Diff line number Diff line change 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+ }
Original file line number Diff line number Diff line change @@ -4,7 +4,7 @@ import Foundation
44
55actor ThreadSafeArray < Element> {
66
7- private var array : [ Element ]
7+ private( set ) var array : [ Element ]
88
99 init ( array: [ Element ] = [ ] ) {
1010 self . array = array
Original file line number Diff line number Diff line change 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+ }
You can’t perform that action at this time.
0 commit comments