|
14 | 14 | // limitations under the License. |
15 | 15 | //===----------------------------------------------------------------------===// |
16 | 16 |
|
17 | | -// `Foundation` will be automatically imported with `SendableProperty`. |
18 | | -@_exported import Foundation |
| 17 | +// `Synchronization` will be automatically imported with `SendableProperty`. |
| 18 | +@_exported import Synchronization |
19 | 19 |
|
20 | 20 | // A declaration of the `@SendableProperty` macro. |
21 | 21 | @attached(peer, names: arbitrary) |
22 | 22 | @attached(accessor) |
23 | 23 | public macro SendableProperty() = #externalMacro(module: "SendablePropertyMacros", type: "SendablePropertyMacro") |
24 | 24 |
|
25 | 25 | /// A synchronization primitive that protects shared mutable state via mutual exclusion. |
26 | | -public final class Synchronized<T>: @unchecked Sendable { |
27 | | - private let lock = NSLock() |
28 | | - private var value: T |
| 26 | +public final class Synchronized<T>: Sendable { |
| 27 | + private let lock: Mutex<State> |
| 28 | + |
| 29 | + private struct State: @unchecked Sendable { |
| 30 | + var value: T |
| 31 | + } |
29 | 32 |
|
30 | 33 | /// Creates a new instance. |
31 | 34 | /// - Parameter value: The initial value. |
32 | 35 | public init(_ value: T) { |
33 | | - self.value = value |
| 36 | + self.lock = Mutex(State(value: value)) |
34 | 37 | } |
35 | 38 |
|
36 | 39 | /// Calls the given closure after acquiring the lock and returns its value. |
37 | 40 | /// - Parameter body: The body of code to execute while the lock is held. |
38 | 41 | public func withLock<R>(_ body: (inout T) throws -> R) rethrows -> R { |
39 | | - lock.lock() |
40 | | - defer { |
41 | | - lock.unlock() |
| 42 | + try lock.withLock { state in |
| 43 | + try body(&state.value) |
42 | 44 | } |
43 | | - return try body(&value) |
44 | 45 | } |
45 | 46 | } |
0 commit comments