Skip to content

Commit b79ce68

Browse files
committed
Add speculative concurrency bug workaround.
1 parent 17eddbf commit b79ce68

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// FileNameHashes.swift
3+
// ImageCache
4+
//
5+
// Created by Jared Sinclair on 11/10/24.
6+
//
7+
8+
import Foundation
9+
import Etcetera
10+
import CryptoKit
11+
12+
public enum FileNameHashes {
13+
14+
/// Your app can provide something stronger than the default implementation
15+
/// (a string representation of a SHA1 hash) if so desired.
16+
public static func registerFileNameHasher(block: @escaping (URL) -> String) {
17+
_uniqueFilenameFromUrl.access {
18+
$0 = block
19+
}
20+
}
21+
22+
static func uniqueFilename(from url: URL) -> String {
23+
_uniqueFilenameFromUrl.current(url)
24+
}
25+
26+
private static let _uniqueFilenameFromUrl: Protected<(URL) -> String> = Protected(Insecure.SHA1.filename(for:))
27+
28+
}

Sources/ImageCache/ImageCache.swift

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
// swiftlint:disable nesting - Seriously, why do we even Swift then.
1111
// swiftlint:disable function_parameter_count - Some problems are hard.
1212

13-
import CryptoKit
1413
import Etcetera
1514
import Combine
1615

@@ -48,13 +47,6 @@ import AppKit
4847
didSet { trimStaleFiles() }
4948
}
5049

51-
/// Your app can provide something stronger than the default implementation
52-
/// (a string representation of a SHA1 hash) if so desired.
53-
public nonisolated var uniqueFilenameFromUrl: (URL) -> String {
54-
get { _uniqueFilenameFromUrl.current }
55-
set { _uniqueFilenameFromUrl.current = newValue }
56-
}
57-
5850
/// When `true` this will empty the in-memory cache when the app enters the
5951
/// background. This can help reduce the likelihood that your app will be
6052
/// terminated in order to reclaim memory for foregrounded applications.
@@ -75,7 +67,6 @@ import AppKit
7567
private let formattingQueue: OperationQueue
7668
private let diskWritingQueue: OperationQueue
7769
private let workQueue: OperationQueue
78-
private nonisolated let _uniqueFilenameFromUrl: Protected<(URL) -> String>
7970
private var cancellables = Set<AnyCancellable>()
8071

8172
// MARK: Init / Deinit
@@ -94,7 +85,6 @@ import AppKit
9485
directory: URL = ImageCache.defaultDirectory,
9586
byteLimitForFileStorage: Bytes? = .fromMegabytes(500)
9687
) {
97-
self._uniqueFilenameFromUrl = Protected(Insecure.SHA1.filename(for:))
9888
self.directory = directory
9989
self.byteLimitForFileStorage = byteLimitForFileStorage
10090
self.urlSession = {
@@ -543,7 +533,7 @@ import AppKit
543533
switch key.source {
544534
case .url(let url):
545535
let originalKey = ImageKey(source: .url(url), format: .original)
546-
filename = uniqueFilenameFromUrl(url) + originalKey.filenameSuffix
536+
filename = FileNameHashes.uniqueFilename(from: url) + originalKey.filenameSuffix
547537
case .manuallySeeded(let id):
548538
filename = "\(id).MANUALLY_SEEDED_ORIGINAL"
549539
case .custom(let id, let namespace, _):
@@ -558,7 +548,7 @@ import AppKit
558548
let filename: String
559549
switch key.source {
560550
case .url(let url):
561-
filename = uniqueFilenameFromUrl(url) + key.filenameSuffix
551+
filename = FileNameHashes.uniqueFilename(from: url) + key.filenameSuffix
562552
case .manuallySeeded(let id):
563553
filename = "\(id).\(key.filenameSuffix)"
564554
case .custom(let identifier, let namespace, _):

0 commit comments

Comments
 (0)