@@ -4,90 +4,116 @@ import Foundation
4
4
///
5
5
/// If you trust the sendability of the underlying value, consider using ``UncheckedSendable``,
6
6
/// instead.
7
- #if compiler(>=6)
8
- @available ( iOS, deprecated: 10000 , message: " Use 'Mutex', instead. " )
9
- @available ( macOS, deprecated: 10000 , message: " Use 'Mutex', instead. " )
10
- @available ( tvOS, deprecated: 10000 , message: " Use 'Mutex', instead. " )
11
- @available ( watchOS, deprecated: 10000 , message: " Use 'Mutex', instead. " )
12
- #endif
13
7
@dynamicMemberLookup
14
8
public final class LockIsolated < Value> : @unchecked Sendable {
15
9
private var _value : Value
16
10
private let lock = NSRecursiveLock ( )
17
11
18
- /// Initializes lock-isolated state around a value.
19
- ///
20
- /// - Parameter value: A value to isolate with a lock.
21
- public init ( _ value: @autoclosure @Sendable ( ) throws -> Value ) rethrows {
22
- self . _value = try value ( )
23
- }
12
+ #if compiler(>=6)
13
+ /// Initializes lock-isolated state around a value.
14
+ ///
15
+ /// - Parameter value: A value to isolate with a lock.
16
+ public init ( _ value: sending @autoclosure ( ) throws -> sending Value) rethrows {
17
+ self . _value = try value ( )
18
+ }
19
+ #else
20
+ public init ( _ value: @autoclosure @Sendable ( ) throws -> Value ) rethrows {
21
+ self . _value = try value ( )
22
+ }
23
+ #endif
24
24
25
- public subscript< Subject: Sendable > ( dynamicMember keyPath: KeyPath < Value , Subject > ) -> Subject {
26
- self . lock. sync {
27
- self . _value [ keyPath: keyPath]
25
+ #if compiler(>=6)
26
+ public subscript< Subject> ( dynamicMember keyPath: KeyPath < Value , Subject > ) -> sending Subject {
27
+ self . lock. sync {
28
+ self . _value [ keyPath: keyPath]
29
+ }
28
30
}
29
- }
31
+ #else
32
+ public subscript< Subject: Sendable > ( dynamicMember keyPath: KeyPath < Value , Subject > ) -> Subject {
33
+ self . lock. sync {
34
+ self . _value [ keyPath: keyPath]
35
+ }
36
+ }
37
+ #endif
30
38
31
- /// Perform an operation with isolated access to the underlying value.
32
- ///
33
- /// Useful for modifying a value in a single transaction.
34
- ///
35
- /// ```swift
36
- /// // Isolate an integer for concurrent read/write access:
37
- /// var count = LockIsolated(0)
38
- ///
39
- /// func increment() {
40
- /// // Safely increment it:
41
- /// self.count.withValue { $0 += 1 }
42
- /// }
43
- /// ```
44
- ///
45
- /// - Parameter operation: An operation to be performed on the the underlying value with a lock.
46
- /// - Returns: The result of the operation .
47
- public func withValue < T : Sendable > (
48
- _ operation : @ Sendable ( inout Value ) throws -> T
49
- ) rethrows -> T {
50
- try self . lock . sync {
51
- var value = self . _value
52
- defer { self . _value = value }
53
- return try operation ( & value )
39
+ #if compiler(>=6)
40
+ /// Perform an operation with isolated access to the underlying value.
41
+ ///
42
+ /// Useful for modifying a value in a single transaction.
43
+ ///
44
+ /// ```swift
45
+ /// // Isolate an integer for concurrent read/write access:
46
+ /// var count = LockIsolated(0)
47
+ ///
48
+ /// func increment() {
49
+ /// // Safely increment it:
50
+ /// self.count.withValue { $0 += 1 }
51
+ /// }
52
+ /// ```
53
+ ///
54
+ /// - Parameter operation: An operation to be performed on the the underlying value with a lock .
55
+ /// - Returns: The result of the operation.
56
+ public func withValue < T > (
57
+ _ operation : sending ( inout sending Value ) throws -> sending T
58
+ ) rethrows -> T {
59
+ try self . lock . sync {
60
+ try operation ( & _value )
61
+ }
54
62
}
55
- }
63
+ #else
64
+ public func withValue< T: Sendable > (
65
+ _ operation: @Sendable ( inout Value ) throws -> T
66
+ ) rethrows -> T {
67
+ try self . lock. sync {
68
+ var value = self . _value
69
+ defer { self . _value = value }
70
+ return try operation ( & value)
71
+ }
72
+ }
73
+ #endif
56
74
57
- /// Overwrite the isolated value with a new value.
58
- ///
59
- /// ```swift
60
- /// // Isolate an integer for concurrent read/write access:
61
- /// var count = LockIsolated(0)
62
- ///
63
- /// func reset() {
64
- /// // Reset it:
65
- /// self.count.setValue(0)
66
- /// }
67
- /// ```
68
- ///
69
- /// > Tip: Use ``withValue(_:)`` instead of ``setValue(_:)`` if the value being set is derived
70
- /// > from the current value. That is, do this:
71
- /// >
72
- /// > ```swift
73
- /// > self.count.withValue { $0 += 1 }
74
- /// > ```
75
- /// >
76
- /// > ...and not this:
77
- /// >
78
- /// > ```swift
79
- /// > self.count.setValue(self.count + 1)
80
- /// > ```
81
- /// >
82
- /// > ``withValue(_:)`` isolates the entire transaction and avoids data races between reading and
83
- /// > writing the value.
84
- ///
85
- /// - Parameter newValue: The value to replace the current isolated value with.
86
- public func setValue( _ newValue: @autoclosure @Sendable ( ) throws -> Value ) rethrows {
87
- try self . lock. sync {
88
- self . _value = try newValue ( )
75
+ #if compiler(>=6)
76
+ /// Overwrite the isolated value with a new value.
77
+ ///
78
+ /// ```swift
79
+ /// // Isolate an integer for concurrent read/write access:
80
+ /// var count = LockIsolated(0)
81
+ ///
82
+ /// func reset() {
83
+ /// // Reset it:
84
+ /// self.count.setValue(0)
85
+ /// }
86
+ /// ```
87
+ ///
88
+ /// > Tip: Use ``withValue(_:)`` instead of ``setValue(_:)`` if the value being set is derived
89
+ /// > from the current value. That is, do this:
90
+ /// >
91
+ /// > ```swift
92
+ /// > self.count.withValue { $0 += 1 }
93
+ /// > ```
94
+ /// >
95
+ /// > ...and not this:
96
+ /// >
97
+ /// > ```swift
98
+ /// > self.count.setValue(self.count + 1)
99
+ /// > ```
100
+ /// >
101
+ /// > ``withValue(_:)`` isolates the entire transaction and avoids data races between reading and
102
+ /// > writing the value.
103
+ ///
104
+ /// - Parameter newValue: The value to replace the current isolated value with.
105
+ public func setValue( _ newValue: sending @autoclosure ( ) throws -> sending Value) rethrows {
106
+ try self . lock. sync {
107
+ self . _value = try newValue ( )
108
+ }
89
109
}
90
- }
110
+ #else
111
+ public func setValue( _ newValue: @autoclosure @Sendable ( ) throws -> Value ) rethrows {
112
+ try self . lock. sync {
113
+ self . _value = try newValue ( )
114
+ }
115
+ }
116
+ #endif
91
117
}
92
118
93
119
extension LockIsolated where Value: Sendable {
0 commit comments