Skip to content

Commit 8f14191

Browse files
authored
Merge pull request #21 from swiftty/feature/actor
actor
2 parents 35082e1 + ab8d8eb commit 8f14191

File tree

10 files changed

+276
-218
lines changed

10 files changed

+276
-218
lines changed

Package.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import PackageDescription
66
let package = Package(
77
name: "DataCacheKit",
88
platforms: [
9-
.iOS(.v14),
10-
.tvOS(.v14),
11-
.watchOS(.v8),
12-
.macOS(.v12)
9+
.iOS(.v16),
10+
.tvOS(.v16),
11+
.watchOS(.v9),
12+
.visionOS(.v2),
13+
.macOS(.v13)
1314
],
1415
products: [
1516
// Products define the executables and libraries a package produces, and make them visible to other packages.

Sources/DataCacheKit/Cache.swift

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import Foundation
22
import OSLog
33

4-
public final class Cache<Key: Hashable & Sendable, Value: Codable & Sendable>: Caching, @unchecked Sendable {
5-
public typealias Options = (forMemory: MemoryCache<Key, Value>.Options, forDisk: DiskCache<Key>.Options)
4+
public actor Cache<Key: Hashable & Sendable, Value: Codable & Sendable>: Caching {
5+
public struct Options: Sendable {
6+
public let forMemory: MemoryCache<Key, Value>.Options
7+
public let forDisk: DiskCache<Key>.Options
8+
9+
public init(forMemory: MemoryCache<Key, Value>.Options, forDisk: DiskCache<Key>.Options) {
10+
self.forMemory = forMemory
11+
self.forDisk = forDisk
12+
}
13+
}
614

7-
public let options: Options
8-
public let logger: Logger
15+
public nonisolated let options: Options
16+
public nonisolated let logger: Logger
917

1018
public subscript (key: Key) -> Value? {
1119
get async throws {
@@ -16,7 +24,6 @@ public final class Cache<Key: Hashable & Sendable, Value: Codable & Sendable>: C
1624
private let onMemery: MemoryCache<Key, Value>
1725
private let onDisk: DiskCache<Key>
1826

19-
private let queueingLock = NSLock()
2027
private var queueingTask: Task<Void, Never>?
2128

2229
public init(options: Options, logger: Logger = .init(.disabled)) {
@@ -26,8 +33,8 @@ public final class Cache<Key: Hashable & Sendable, Value: Codable & Sendable>: C
2633
self.logger = logger
2734
}
2835

29-
public func prepare() throws {
30-
try onDisk.prepare()
36+
public func prepare() async throws {
37+
try await onDisk.prepare()
3138
}
3239

3340
public func value(for key: Key) async throws -> Value? {
@@ -46,64 +53,48 @@ public final class Cache<Key: Hashable & Sendable, Value: Codable & Sendable>: C
4653
return try decoder.decode(Value.self, from: data)
4754
}()
4855

49-
onMemery.store(value, for: key)
56+
await onMemery.store(value, for: key)
5057
return value
5158
}
5259

5360
@discardableResult
5461
public func store(_ value: Value, for key: Key) -> Task<Void, Never> {
55-
queueingLock.lock()
56-
defer { queueingLock.unlock() }
57-
let oldTask = queueingTask
58-
let task = Task {
59-
await oldTask?.value
62+
queueingTask.enqueueAndReplacing { [weak self] in
63+
guard let self else { return }
6064
async let memory: Void = await onMemery.store(value, for: key).value
6165
async let disk: Void = await _storeToDisk(value, for: key)
6266

6367
await memory
6468
await disk
6569
}
66-
queueingTask = task
67-
return task
6870
}
6971

7072
@discardableResult
7173
public func remove(for key: Key) -> Task<Void, Never> {
72-
queueingLock.lock()
73-
defer { queueingLock.unlock() }
74-
let oldTask = queueingTask
75-
let task = Task {
76-
await oldTask?.value
74+
queueingTask.enqueueAndReplacing { [weak self] in
75+
guard let self else { return }
7776
async let memory: Void = await onMemery.remove(for: key).value
7877
async let disk: Void = await onDisk.remove(for: key).value
7978

8079
await memory
8180
await disk
8281
}
83-
queueingTask = task
84-
return task
8582
}
8683

8784
@discardableResult
8885
public func removeAll() -> Task<Void, Never> {
89-
queueingLock.lock()
90-
defer { queueingLock.unlock() }
91-
let oldTask = queueingTask
92-
let task = Task {
93-
await oldTask?.value
94-
86+
queueingTask.enqueueAndReplacing { [weak self] in
87+
guard let self else { return }
9588
async let memory: Void = await onMemery.removeAll().value
9689
async let disk: Void = await onDisk.removeAll().value
9790

9891
await memory
9992
await disk
10093
}
101-
queueingTask = task
102-
return task
10394
}
10495

105-
public func url(for key: Key) -> URL? {
106-
onDisk.url(for: key)
96+
public func url(for key: Key) async -> URL? {
97+
await onDisk.url(for: key)
10798
}
10899
}
109100

Sources/DataCacheKit/Caching.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
public protocol Caching<Key, Value>: Sendable {
3+
public protocol Caching<Key, Value>: Actor {
44
associatedtype Key: Hashable & Sendable
55
associatedtype Value
66

Sources/DataCacheKit/DiskCache+Options.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import Foundation
22
import CommonCrypto
33

44
extension DiskCache {
5-
public struct Options {
5+
public struct Options: Sendable {
66
public var sizeLimit: Int
77
public var filename: @Sendable (Key) -> String?
88
public var path: Path
99
public var expirationTimeout: TimeInterval?
1010

11-
public enum Path {
11+
public enum Path: Sendable {
1212
case `default`(name: String)
1313
case custom(URL)
1414
}

0 commit comments

Comments
 (0)