Skip to content

Commit ff8dadf

Browse files
committed
Remove Atomic Property Wrapper
Atomic property wrapper setters just don't work. Swift grabs the value (with the lock) and then does the operation and then sets the value. There's a small time where the critical section is not protected so we need a class.
1 parent c38300b commit ff8dadf

File tree

3 files changed

+18
-14
lines changed

3 files changed

+18
-14
lines changed

Sources/CodeEditSourceEditor/TreeSitter/Atomic.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@
88
import Foundation
99

1010
/// A simple atomic value using `NSLock`.
11-
@propertyWrapper
1211
final package class Atomic<T> {
1312
private let lock: NSLock = .init()
14-
private var _wrappedValue: T
13+
private var wrappedValue: T
1514

16-
package var wrappedValue: T {
17-
get {
18-
return lock.withLock { _wrappedValue }
19-
}
20-
set {
21-
lock.withLock { _wrappedValue = newValue }
15+
init(_ wrappedValue: T) {
16+
self.wrappedValue = wrappedValue
17+
}
18+
19+
func mutate(_ handler: (inout T) -> Void) {
20+
lock.withLock {
21+
handler(&wrappedValue)
2222
}
2323
}
2424

25-
package init(wrappedValue: T) {
26-
self._wrappedValue = wrappedValue
25+
func value() -> T {
26+
lock.withLock { wrappedValue }
2727
}
2828
}

Sources/CodeEditSourceEditor/TreeSitter/TreeSitterClient+Edit.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extension TreeSitterClient {
1919
/// - Returns: The set of ranges invalidated by the edit operation.
2020
func applyEdit(edit: InputEdit) -> IndexSet {
2121
guard let state = state?.copy(), let readBlock, let readCallback else { return IndexSet() }
22-
let pendingEdits = pendingEdits // Grab pending edits.
22+
let pendingEdits = pendingEdits.value() // Grab pending edits.
2323
let edits = pendingEdits + [edit]
2424

2525
var invalidatedRanges = IndexSet()
@@ -61,7 +61,9 @@ extension TreeSitterClient {
6161
if Task.isCancelled { return IndexSet() }
6262

6363
self.state = state // Apply the copied state
64-
self.pendingEdits = [] // Clear the queue
64+
self.pendingEdits.mutate { edits in // Clear the queue
65+
edits = []
66+
}
6567

6668
return invalidatedRanges
6769
}

Sources/CodeEditSourceEditor/TreeSitter/TreeSitterClient.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public final class TreeSitterClient: HighlightProviding {
4949
/// The end point of the previous edit.
5050
private var oldEndPoint: Point?
5151

52-
@Atomic package var pendingEdits: [InputEdit] = []
52+
package var pendingEdits: Atomic<[InputEdit]> = Atomic([])
5353

5454
/// Optional flag to force every operation to be done on the caller's thread.
5555
var forceSyncOperation: Bool = false
@@ -168,7 +168,9 @@ public final class TreeSitterClient: HighlightProviding {
168168
priority: .edit,
169169
operation: operation,
170170
onCancel: { [weak self] in
171-
self?.pendingEdits.append(edit)
171+
self?.pendingEdits.mutate { edits in
172+
edits.append(edit)
173+
}
172174
DispatchQueue.dispatchMainIfNot {
173175
completion(.failure(HighlightProvidingError.operationCancelled))
174176
}

0 commit comments

Comments
 (0)