|
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