|
5 | 5 | * http://stregasgate.com |
6 | 6 | */ |
7 | 7 |
|
8 | | -#if canImport(Atomics) |
9 | | -public import Atomics |
10 | | -#elseif canImport(Foundation.NSLock) |
11 | | -import class Foundation.NSLock |
12 | | -#endif |
| 8 | +// A protocol to make sure all the possible variations have the same interface |
| 9 | +public protocol IDGeneratorProtocol: Sendable { |
| 10 | + associatedtype T: BinaryInteger & Sendable |
| 11 | + func generateID() -> T |
| 12 | + init(startValue: T) |
| 13 | +} |
13 | 14 |
|
14 | 15 | #if canImport(Atomics) |
15 | | -nonisolated public final class IDGenerator<T: AtomicInteger & Sendable> { |
| 16 | +public import Atomics |
| 17 | +public struct IDGenerator<T: AtomicInteger & Sendable>: IDGeneratorProtocol { |
16 | 18 | var value: ManagedAtomic<T> |
17 | | - |
18 | 19 | public init(startValue: T = 0) { |
19 | 20 | value = ManagedAtomic<T>(startValue) |
20 | 21 | } |
21 | 22 |
|
22 | 23 | public func generateID() -> T { |
23 | | - return value.loadThenWrappingIncrement(ordering: .sequentiallyConsistent) |
| 24 | + return value.loadThenWrappingIncrement(ordering: .relaxed) |
24 | 25 | } |
25 | 26 | } |
26 | 27 | #elseif canImport(Foundation.NSLock) |
27 | | -nonisolated public final class IDGenerator<T: BinaryInteger & Sendable> { |
28 | | - var value: T = 0 |
| 28 | +import class Foundation.NSLock |
| 29 | +public final class IDGenerator<T: BinaryInteger & Sendable>: IDGeneratorProtocol { |
| 30 | + // isolation is managed with a lock, so this is safe |
| 31 | + nonisolated(unsafe) var value: T = 0 |
29 | 32 | let lock = NSLock() |
30 | 33 |
|
31 | 34 | public init(startValue: T = 0) { |
32 | 35 | self.value = startValue |
33 | 36 | } |
34 | 37 |
|
35 | 38 | public func generateID() -> T { |
36 | | - lock.lock() |
37 | | - let value = value |
38 | | - self.value += 1 |
39 | | - defer { |
40 | | - lock.unlock() |
| 39 | + return lock.withLock { |
| 40 | + let value = value |
| 41 | + self.value += 1 |
| 42 | + return value |
41 | 43 | } |
42 | | - return value |
43 | 44 | } |
44 | 45 | } |
45 | 46 | #else |
46 | | -nonisolated public final class IDGenerator<T: BinaryInteger & Sendable> { |
47 | | - var value: T = 0 |
| 47 | +public final class IDGenerator<T: BinaryInteger & Sendable>: IDGeneratorProtocol { |
| 48 | + nonisolated(unsafe) var value: T = 0 |
48 | 49 |
|
49 | 50 | public init(startValue: T = 0) { |
50 | 51 | self.value = startValue |
|
0 commit comments