Skip to content

Commit 577b925

Browse files
Seweryn Plażuksewerynplazuk
authored andcommitted
Add thread safety to Clock
Signed-off-by: Seweryn Plażuk <[email protected]>
1 parent 1b2d25b commit 577b925

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

Kronos.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
930B39DD2051E6D300360BA2 /* TimeStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930B39DC2051E6D300360BA2 /* TimeStorage.swift */; };
2424
930B39E02051F26500360BA2 /* TimeStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930B39DE2051F25300360BA2 /* TimeStorageTests.swift */; };
2525
C201748E1BD5509D00E4FE18 /* Kronos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C20174831BD5509D00E4FE18 /* Kronos.framework */; };
26+
E5CC90032BFCA6C2009B0B82 /* UnfairLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CC90022BFCA6C2009B0B82 /* UnfairLock.swift */; };
2627
/* End PBXBuildFile section */
2728

2829
/* Begin PBXContainerItemProxy section */
@@ -58,6 +59,7 @@
5859
C2C036D41C2B180D003FB853 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = "<group>"; };
5960
C2C036D51C2B180D003FB853 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = "<group>"; };
6061
C2C036D61C2B180D003FB853 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = "<group>"; };
62+
E5CC90022BFCA6C2009B0B82 /* UnfairLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnfairLock.swift; sourceTree = "<group>"; };
6163
/* End PBXFileReference section */
6264

6365
/* Begin PBXFrameworksBuildPhase section */
@@ -124,6 +126,7 @@
124126
26447D7B1D6E54D400159BEE /* TimeFreeze.swift */,
125127
930B39DC2051E6D300360BA2 /* TimeStorage.swift */,
126128
5DB5A05F2BAAF67D0069CCF9 /* PrivacyInfo.xcprivacy */,
129+
E5CC90022BFCA6C2009B0B82 /* UnfairLock.swift */,
127130
);
128131
path = Sources;
129132
sourceTree = "<group>";
@@ -234,6 +237,7 @@
234237
26447D7E1D6E54D400159BEE /* InternetAddress.swift in Sources */,
235238
26447D811D6E54D400159BEE /* NTPClient.swift in Sources */,
236239
26447D7F1D6E54D400159BEE /* Data+Bytes.swift in Sources */,
240+
E5CC90032BFCA6C2009B0B82 /* UnfairLock.swift in Sources */,
237241
26447D841D6E54D400159BEE /* TimeFreeze.swift in Sources */,
238242
26447D821D6E54D400159BEE /* NTPPacket.swift in Sources */,
239243
26447D801D6E54D400159BEE /* NSTimer+ClosureKit.swift in Sources */,

Sources/Clock.swift

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,39 @@ public typealias AnnotatedTime = (
2525
/// print(Clock.now)
2626
/// ```
2727
public struct Clock {
28+
private static let unfairLock = UnfairLock()
29+
30+
private static var _stableTime: TimeFreeze?
31+
private static var _storage = TimeStorage(storagePolicy: .standard)
32+
2833
private static var stableTime: TimeFreeze? {
29-
didSet {
30-
self.storage.stableTime = self.stableTime
34+
get {
35+
self.unfairLock.synchronized {
36+
return self._stableTime
37+
}
38+
}
39+
set {
40+
self.unfairLock.synchronized {
41+
self._stableTime = newValue
42+
self._storage.stableTime = newValue
43+
}
3144
}
3245
}
3346

3447
/// Determines where the most current stable time is stored. Use TimeStoragePolicy.appGroup to share
3548
/// between your app and an extension.
36-
public static var storage = TimeStorage(storagePolicy: .standard)
49+
public static var storage: TimeStorage {
50+
get {
51+
self.unfairLock.synchronized {
52+
return self._storage
53+
}
54+
}
55+
set {
56+
self.unfairLock.synchronized {
57+
self._storage = newValue
58+
}
59+
}
60+
}
3761

3862
/// The most accurate timestamp that we have so far (nil if no synchronization was done yet)
3963
public static var timestamp: TimeInterval? {

Sources/UnfairLock.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os.lock
2+
3+
final class UnfairLock {
4+
private let lockPointer: os_unfair_lock_t
5+
6+
init() {
7+
self.lockPointer = .allocate(capacity: 1)
8+
self.lockPointer.initialize(to: os_unfair_lock())
9+
}
10+
11+
deinit {
12+
self.lockPointer.deinitialize(count: 1)
13+
self.lockPointer.deallocate()
14+
}
15+
16+
func synchronized<T>(_ block: () -> T) -> T {
17+
self.lock()
18+
defer { self.unlock() }
19+
return block()
20+
}
21+
22+
private func lock() {
23+
os_unfair_lock_lock(self.lockPointer)
24+
}
25+
26+
private func unlock() {
27+
os_unfair_lock_unlock(self.lockPointer)
28+
}
29+
}

0 commit comments

Comments
 (0)