diff --git a/Sources/SWBUtil/AsyncLock.swift b/Sources/SWBUtil/AsyncLock.swift index c2a5d5c6..5a7c3d34 100644 --- a/Sources/SWBUtil/AsyncLock.swift +++ b/Sources/SWBUtil/AsyncLock.swift @@ -18,7 +18,7 @@ public actor ActorLock { public init() { } - public func withLock(_ body: @Sendable () async throws(E) -> T) async throws(E) -> T { + public func withLock(_ body: sending () async throws(E) -> T) async throws(E) -> T { while busy { await withCheckedContinuation { cc in queue.append(cc) @@ -47,7 +47,7 @@ public final class AsyncLockedValue { } @discardableResult @inlinable - public func withLock(_ block: @Sendable (inout Wrapped) async throws(E) -> Result) async throws(E) -> Result { + public func withLock(_ block: sending (inout Wrapped) async throws(E) -> Result) async throws(E) -> Result { return try await lock.withLock { () throws(E) -> Result in try await block(&value) } } } diff --git a/Sources/SWBUtil/HeavyCache.swift b/Sources/SWBUtil/HeavyCache.swift index 190457e2..25cbd479 100644 --- a/Sources/SWBUtil/HeavyCache.swift +++ b/Sources/SWBUtil/HeavyCache.swift @@ -14,6 +14,8 @@ import os #endif +import Synchronization + /// Base protocol used for global operations over generic type. private protocol _HeavyCacheBase: AnyObject { /// Clear the cache. @@ -60,7 +62,7 @@ public func withHeavyCacheGlobalState(isolated: Bool = true, _ body: () throw /// A cache designed for holding few, relatively heavy-weight objects. /// /// This cache is specifically designed for holding a limited number of objects (usually less than 100) which are expensive enough to merit particular attention in terms of being purgeable under memory pressure, evictable in-mass, or cached with more complex parameters like time-to-live (TTL). -public final class HeavyCache: _HeavyCacheBase, KeyValueStorage, @unchecked Sendable { +public final class HeavyCache: _HeavyCacheBase, KeyValueStorage, @unchecked Sendable { public typealias HeavyCacheClock = SuspendingClock /// Controls the non-deterministic eviction policy of the cache. Note that this is distinct from deterministic _pruning_ (due to TTL or size limits). @@ -86,7 +88,7 @@ public final class HeavyCache: _HeavyCacheBase, KeyValueSt } /// The lock to protect shared instance state. - private let stateLock = Lock() + private let stateLock = SWBMutex(()) /// The underlying cache. private let _cache: any HeavyCacheImpl diff --git a/Sources/SWBUtil/InterningArena.swift b/Sources/SWBUtil/InterningArena.swift index c7f2c95e..11ca1435 100644 --- a/Sources/SWBUtil/InterningArena.swift +++ b/Sources/SWBUtil/InterningArena.swift @@ -18,7 +18,7 @@ public typealias FrozenStringArena = FrozenInterningArena private let numberOfInternCalls = Statistic("InterningArena.numberOfInternCalls", "Number of calls to 'InterningArena.intern'") private let numberOfItemsInterned = Statistic("InterningArena.numberOfItemsInterned", "Number of items interned in InterningArenas") -public final class InterningArena { +public final class InterningArena { public struct Handle: Hashable, Sendable { fileprivate let value: UInt32 diff --git a/Sources/SWBUtil/Lock.swift b/Sources/SWBUtil/Lock.swift index d0334e6f..abc1664a 100644 --- a/Sources/SWBUtil/Lock.swift +++ b/Sources/SWBUtil/Lock.swift @@ -110,7 +110,7 @@ extension LockedValue where Value: ~Copyable { extension LockedValue: @unchecked Sendable where Value: ~Copyable { } -extension LockedValue { +extension LockedValue where Value: Sendable { /// Sets the value of the wrapped value to `newValue` and returns the original value. public func exchange(_ newValue: Value) -> Value { withLock { diff --git a/Sources/SWBUtil/Statistics.swift b/Sources/SWBUtil/Statistics.swift index 7f7eed87..7d9fd51b 100644 --- a/Sources/SWBUtil/Statistics.swift +++ b/Sources/SWBUtil/Statistics.swift @@ -115,7 +115,7 @@ public final class Statistic: @unchecked Sendable, _StatisticBackend { } } -public protocol _StatisticBackend { +public protocol _StatisticBackend: Sendable { var name: String { get } var value: Int { get } func increment(_ n: Int)