Skip to content

Commit

Permalink
Fix Sendable warnings, and in the process also the behavior of ISO860…
Browse files Browse the repository at this point in the history
…1TimestampFormat when both fractional and non-fractional formats are used in the same project.
  • Loading branch information
gwynne committed May 29, 2024
1 parent ba5bcab commit d2a4f38
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
4 changes: 4 additions & 0 deletions Sources/FluentBenchmark/Tests/PerformanceTests.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import FluentKit
#if !canImport(Darwin)
@preconcurrency import Foundation
#else
import Foundation
#endif
import NIOCore
import XCTest

Expand Down
22 changes: 15 additions & 7 deletions Sources/FluentKit/Properties/TimestampFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,26 @@ extension TimestampFormatFactory {
withMilliseconds: Bool
) -> TimestampFormatFactory<ISO8601TimestampFormat> {
.init {
ISO8601DateFormatter.shared.withLockedValue {
if withMilliseconds {
$0.formatOptions.insert(.withFractionalSeconds)
}
return ISO8601TimestampFormat(formatter: $0)
}
ISO8601TimestampFormat(formatter: (withMilliseconds ?
ISO8601DateFormatter.sharedWithMs :
ISO8601DateFormatter.sharedWithoutMs
).value)
}
}
}

extension ISO8601DateFormatter {
fileprivate static let shared: NIOLockedValueBox<ISO8601DateFormatter> = .init(.init())
// We use this to suppress warnings about ISO8601DateFormatter not being Sendable. It's safe to do so because we
// know that in reality, the formatter is safe to use simultaneously from multiple threads as long as the options
// are not changed, and we never change the options after the formatter is first created.
fileprivate struct FakeSendable<T>: @unchecked Sendable { let value: T }

fileprivate static let sharedWithoutMs: FakeSendable<ISO8601DateFormatter> = .init(value: .init())
fileprivate static let sharedWithMs: FakeSendable<ISO8601DateFormatter> = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions.insert(.withFractionalSeconds)
return .init(value: formatter)
}()
}

public struct ISO8601TimestampFormat: TimestampFormat, @unchecked Sendable {
Expand Down

0 comments on commit d2a4f38

Please # to comment.