Fix Sendability warnings (#137)
* Fix Sendability warnings * Apply suggestions from code review * Fix another warning and @unknown default issue --------- Co-authored-by: Konrad `ktoso` Malawski <konrad.malawski@project13.pl>
This commit is contained in:
parent
d067b0e0f7
commit
e0165b53d4
|
|
@ -131,6 +131,8 @@ extension Lock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Lock: @unchecked Sendable {}
|
||||||
|
|
||||||
/// A reader/writer threading lock based on `libpthread` instead of `libdispatch`.
|
/// A reader/writer threading lock based on `libpthread` instead of `libdispatch`.
|
||||||
///
|
///
|
||||||
/// This object provides a lock on top of a single `pthread_rwlock_t`. This kind
|
/// This object provides a lock on top of a single `pthread_rwlock_t`. This kind
|
||||||
|
|
@ -273,3 +275,5 @@ extension ReadWriteLock {
|
||||||
try self.withWriterLock(body)
|
try self.withWriterLock(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ReadWriteLock: @unchecked Sendable {}
|
||||||
|
|
|
||||||
|
|
@ -600,7 +600,8 @@ public enum MetricsSystem {
|
||||||
return try self._factory.withWriterLock(body)
|
return try self._factory.withWriterLock(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class FactoryBox {
|
// This can be `@unchecked Sendable` because we're manually gating access to mutable state with a lock.
|
||||||
|
private final class FactoryBox: @unchecked Sendable {
|
||||||
private let lock = ReadWriteLock()
|
private let lock = ReadWriteLock()
|
||||||
fileprivate var _underlying: MetricsFactory
|
fileprivate var _underlying: MetricsFactory
|
||||||
private var initialized = false
|
private var initialized = false
|
||||||
|
|
@ -797,9 +798,10 @@ internal final class AccumulatingRoundingFloatingPointCounter: FloatingPointCoun
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a RecorderHandler, adding support for incrementing values by storing an accumulated value and recording increments to the underlying CounterHandler after crossing integer boundaries.
|
/// Wraps a RecorderHandler, adding support for incrementing values by storing an accumulated value and recording increments to the underlying CounterHandler after crossing integer boundaries.
|
||||||
internal final class AccumulatingMeter: MeterHandler {
|
/// - Note: we can annotate this class as `@unchecked Sendable` because we are manually gating access to mutable state (i.e., the `value` property) via a Lock.
|
||||||
|
internal final class AccumulatingMeter: MeterHandler, @unchecked Sendable {
|
||||||
private let recorderHandler: RecorderHandler
|
private let recorderHandler: RecorderHandler
|
||||||
// FIXME: use atomics when available
|
// FIXME: use swift-atomics when floating point support is available
|
||||||
private var value: Double = 0
|
private var value: Double = 0
|
||||||
private let lock = Lock()
|
private let lock = Lock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,16 @@ extension Timer {
|
||||||
/// - duration: The duration to record.
|
/// - duration: The duration to record.
|
||||||
@inlinable
|
@inlinable
|
||||||
public func record(_ duration: DispatchTimeInterval) {
|
public func record(_ duration: DispatchTimeInterval) {
|
||||||
|
// This wrapping in a optional is a workaround because DispatchTimeInterval
|
||||||
|
// is a non-frozen public enum and Dispatch is built with library evolution
|
||||||
|
// mode turned on.
|
||||||
|
// This means we should have an `@unknown default` case, but this breaks
|
||||||
|
// on non-Darwin platforms.
|
||||||
|
// Switching over an optional means that the `.none` case will map to
|
||||||
|
// `default` (which means we'll always have a valid case to go into
|
||||||
|
// the default case), but in reality this case will never exist as this
|
||||||
|
// optional will never be nil.
|
||||||
|
let duration = Optional(duration)
|
||||||
switch duration {
|
switch duration {
|
||||||
case .nanoseconds(let value):
|
case .nanoseconds(let value):
|
||||||
self.recordNanoseconds(value)
|
self.recordNanoseconds(value)
|
||||||
|
|
@ -71,6 +81,8 @@ extension Timer {
|
||||||
self.recordSeconds(value)
|
self.recordSeconds(value)
|
||||||
case .never:
|
case .never:
|
||||||
self.record(0)
|
self.record(0)
|
||||||
|
default:
|
||||||
|
self.record(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,17 @@ class MetricsExtensionsTests: XCTestCase {
|
||||||
// https://bugs.swift.org/browse/SR-6310
|
// https://bugs.swift.org/browse/SR-6310
|
||||||
extension DispatchTimeInterval {
|
extension DispatchTimeInterval {
|
||||||
func nano() -> Int {
|
func nano() -> Int {
|
||||||
switch self {
|
// This wrapping in a optional is a workaround because DispatchTimeInterval
|
||||||
|
// is a non-frozen public enum and Dispatch is built with library evolution
|
||||||
|
// mode turned on.
|
||||||
|
// This means we should have an `@unknown default` case, but this breaks
|
||||||
|
// on non-Darwin platforms.
|
||||||
|
// Switching over an optional means that the `.none` case will map to
|
||||||
|
// `default` (which means we'll always have a valid case to go into
|
||||||
|
// the default case), but in reality this case will never exist as this
|
||||||
|
// optional will never be nil.
|
||||||
|
let interval = Optional(self)
|
||||||
|
switch interval {
|
||||||
case .nanoseconds(let value):
|
case .nanoseconds(let value):
|
||||||
return value
|
return value
|
||||||
case .microseconds(let value):
|
case .microseconds(let value):
|
||||||
|
|
@ -196,6 +206,8 @@ extension DispatchTimeInterval {
|
||||||
return value * 1_000_000_000
|
return value * 1_000_000_000
|
||||||
case .never:
|
case .never:
|
||||||
return 0
|
return 0
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue