Skip to content

Commit 46c747b

Browse files
authored
Make atom keys Sendable for better sendable concurrency compatibility (#152)
1 parent 64b6392 commit 46c747b

File tree

13 files changed

+45
-29
lines changed

13 files changed

+45
-29
lines changed

Examples/Packages/iOS/Sources/ExampleVoiceMemo/Atoms/VoiceMemoRowAtoms.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import SwiftUI
77
struct IsPlayingAtom: StateAtom {
88
let voiceMemo: VoiceMemo
99

10-
var key: some Hashable {
10+
var key: URL {
1111
voiceMemo.url
1212
}
1313

@@ -39,7 +39,7 @@ struct IsPlayingAtom: StateAtom {
3939
struct PlayingElapsedTimeAtom: PublisherAtom {
4040
let voiceMemo: VoiceMemo
4141

42-
var key: some Hashable {
42+
var key: URL {
4343
voiceMemo.url
4444
}
4545

@@ -58,7 +58,7 @@ struct PlayingElapsedTimeAtom: PublisherAtom {
5858
struct AudioPlayerAtom: ValueAtom {
5959
let voiceMemo: VoiceMemo
6060

61-
var key: some Hashable {
61+
var key: URL {
6262
voiceMemo.url
6363
}
6464

Sources/Atoms/Core/Atom/Atom.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/// and is immediately released when no longer watched.
55
public protocol Atom<Produced>: Sendable {
66
/// A type representing the stable identity of this atom.
7-
associatedtype Key: Hashable
7+
associatedtype Key: Hashable & Sendable
88

99
/// The type of value that this atom produces.
1010
associatedtype Produced

Sources/Atoms/Core/Atom/ModifiedAtom.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public struct ModifiedAtom<Node: Atom, Modifier: AtomModifier>: Atom where Node.
66
public typealias Produced = Modifier.Produced
77

88
/// A type representing the stable identity of this atom.
9-
public struct Key: Hashable {
9+
public struct Key: Hashable, Sendable {
1010
private let atomKey: Node.Key
1111
private let modifierKey: Modifier.Key
1212

Sources/Atoms/Core/AtomKey.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
internal struct AtomKey: Hashable, CustomStringConvertible {
2-
private let key: AnyHashable
1+
internal struct AtomKey: Hashable, Sendable, CustomStringConvertible {
2+
private let key: UnsafeUncheckedSendable<AnyHashable>
33
private let type: ObjectIdentifier
44
private let scopeKey: ScopeKey?
55
private let anyAtomType: Any.Type
@@ -20,7 +20,7 @@ internal struct AtomKey: Hashable, CustomStringConvertible {
2020
}
2121

2222
init<Node: Atom>(_ atom: Node, scopeKey: ScopeKey?) {
23-
self.key = AnyHashable(atom.key)
23+
self.key = UnsafeUncheckedSendable(atom.key)
2424
self.type = ObjectIdentifier(Node.self)
2525
self.scopeKey = scopeKey
2626
self.anyAtomType = Node.self

Sources/Atoms/Core/Modifier/AtomModifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public extension Atom {
1111
/// A modifier that you apply to an atom, producing a new value modified from the original value.
1212
public protocol AtomModifier: Sendable {
1313
/// A type representing the stable identity of this modifier.
14-
associatedtype Key: Hashable
14+
associatedtype Key: Hashable & Sendable
1515

1616
/// A type of base value to be modified.
1717
associatedtype Base

Sources/Atoms/Core/OverrideKey.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ internal struct OverrideKey: Hashable, Sendable {
44

55
@usableFromInline
66
init<Node: Atom>(_ atom: Node) {
7-
let key = AnyHashable(atom.key)
7+
let key = UnsafeUncheckedSendable<AnyHashable>(atom.key)
88
let type = ObjectIdentifier(Node.self)
99
identifier = .node(key: key, type: type)
1010
}
@@ -17,8 +17,8 @@ internal struct OverrideKey: Hashable, Sendable {
1717
}
1818

1919
private extension OverrideKey {
20-
enum Identifier: Hashable, @unchecked Sendable {
21-
case node(key: AnyHashable, type: ObjectIdentifier)
20+
enum Identifier: Hashable, Sendable {
21+
case node(key: UnsafeUncheckedSendable<AnyHashable>, type: ObjectIdentifier)
2222
case type(ObjectIdentifier)
2323
}
2424
}

Sources/Atoms/Core/ScopeKey.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@usableFromInline
2-
internal struct ScopeKey: Hashable, CustomStringConvertible {
2+
internal struct ScopeKey: Hashable, Sendable, CustomStringConvertible {
33
final class Token {}
44

55
private let identifier: ObjectIdentifier

Sources/Atoms/Core/StoreContext.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ private extension StoreContext {
440440
lazy var shouldKeepAlive = !key.isScoped && store.state.caches[key].map { $0.atom is any KeepAlive } ?? false
441441
lazy var isChildrenEmpty = store.graph.children[key]?.isEmpty ?? true
442442
lazy var isSubscriptionEmpty = store.state.subscriptions[key]?.isEmpty ?? true
443-
lazy var shouldRelease = !shouldKeepAlive && isChildrenEmpty && isSubscriptionEmpty
443+
let shouldRelease = !shouldKeepAlive && isChildrenEmpty && isSubscriptionEmpty
444444

445445
guard shouldRelease else {
446446
return

Sources/Atoms/Core/UnsafeUncheckedSendable.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ internal struct UnsafeUncheckedSendable<Value>: @unchecked Sendable {
77
self.value = value
88
}
99
}
10+
11+
extension UnsafeUncheckedSendable: Equatable where Value: Equatable {}
12+
extension UnsafeUncheckedSendable: Hashable where Value: Hashable {}

Sources/Atoms/Modifier/AnimationModifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public struct AnimationModifier<Produced>: AtomModifier {
4141
public typealias Produced = Produced
4242

4343
/// A type representing the stable identity of this atom associated with an instance.
44-
public struct Key: Hashable {
44+
public struct Key: Hashable, Sendable {
4545
private let animation: Animation?
4646

4747
fileprivate init(animation: Animation?) {

0 commit comments

Comments
 (0)