Skip to content

Commit

Permalink
Add thread safety to Clock
Browse files Browse the repository at this point in the history
Signed-off-by: Seweryn Plażuk <[email protected]>
  • Loading branch information
Seweryn Plażuk authored and sewerynplazuk committed May 22, 2024
1 parent 1b2d25b commit 225a326
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
17 changes: 14 additions & 3 deletions Sources/Clock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,20 @@ public typealias AnnotatedTime = (
/// print(Clock.now)
/// ```
public struct Clock {
private static var stableTime: TimeFreeze? {
didSet {
self.storage.stableTime = self.stableTime
private static let syncQueue = DispatchQueue(label: "kronos.stable.time", attributes: .concurrent)

private static var _stableTime: TimeFreeze?
static var stableTime: TimeFreeze? {
get {
self.syncQueue.sync {
return self._stableTime
}
}
set {
self.syncQueue.async(flags: .barrier) {
self._stableTime = newValue
self.storage.stableTime = newValue
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/TimeFreeze.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ private let kOffsetKey = "Offset"
struct TimeFreeze {
private let uptime: TimeInterval
private let timestamp: TimeInterval
private let offset: TimeInterval
let offset: TimeInterval

/// The stable timestamp adjusted by the most accurate offset known so far.
var adjustedTimestamp: TimeInterval {
Expand Down
30 changes: 30 additions & 0 deletions Tests/KronosTests/ClockTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,34 @@ final class ClockTests: XCTestCase {

self.waitForExpectations(timeout: 20)
}

func testStableTimeThreadSafety() {
let expectation = self.expectation(description: "Concurrent access to stableTime")
expectation.expectedFulfillmentCount = 10

let incrementBlock = {
for _ in 0..<1000 {
let newOffset = {
if let offset = Clock.stableTime?.offset {
return offset + 1
} else {
return 0
}
}()
Clock.stableTime = TimeFreeze(offset: newOffset)
}
}

for _ in 0..<10 {
DispatchQueue.global().async {
incrementBlock()
expectation.fulfill()
}
}

self.waitForExpectations(timeout: 2)

XCTAssertEqual(Clock.stableTime?.offset, 1000)
}

}

0 comments on commit 225a326

Please sign in to comment.