Skip to content

Commit fcd3e8d

Browse files
authored
Atomicity updates for Thread Sanitizer warnings (#237)
* Refactored Atomic implementation to avoid TSan warnings * Additional reference
1 parent d56b150 commit fcd3e8d

File tree

2 files changed

+15
-18
lines changed

2 files changed

+15
-18
lines changed

Sources/Segment/Utilities/Atomic.swift

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,26 @@
77

88
import Foundation
99

10+
// NOTE: Revised from previous implementation which used a struct and NSLock's.
11+
// Thread Sanitizer was *correctly* capturing this issue, which was a little obscure
12+
// given the property wrapper PLUS the semantics of a struct. Moving to `class`
13+
// removes the semantics problem and lets TSan approve of what's happening.
14+
//
15+
// Additionally, moving to a lock free version is just desirable, so moved to a queue.
16+
//
17+
// Also see thread here: https://github.com/apple/swift-evolution/pull/1387
18+
1019
@propertyWrapper
11-
public struct Atomic<T> {
12-
var value: T
13-
private let lock = NSLock()
20+
public class Atomic<T> {
21+
private var value: T
22+
private let queue = DispatchQueue(label: "com.segment.atomic.\(UUID().uuidString)")
1423

1524
public init(wrappedValue value: T) {
1625
self.value = value
1726
}
1827

1928
public var wrappedValue: T {
20-
get { return load() }
21-
set { store(newValue: newValue) }
22-
}
23-
24-
func load() -> T {
25-
lock.lock()
26-
defer { lock.unlock() }
27-
return value
28-
}
29-
30-
mutating func store(newValue: T) {
31-
lock.lock()
32-
defer { lock.unlock() }
33-
value = newValue
29+
get { return queue.sync { return value } }
30+
set { queue.sync { value = newValue } }
3431
}
3532
}

Sources/Segment/Utilities/Policies/CountBasedFlushPolicy.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
public class CountBasedFlushPolicy: FlushPolicy {
1111
public weak var analytics: Analytics?
1212
internal var desiredCount: Int?
13-
internal var count: Int = 0
13+
@Atomic internal var count: Int = 0
1414

1515
init() { }
1616

0 commit comments

Comments
 (0)