File tree 4 files changed +67
-0
lines changed
4 files changed +67
-0
lines changed Original file line number Diff line number Diff line change @@ -35,6 +35,7 @@ This library comes with a number of tools that make working with Swift concurren
35
35
testable.
36
36
37
37
* [ ` LockIsolated ` ] ( #lockisolated )
38
+ * [ ` AnyHashableSendable ` ] ( #anyhashablesendable )
38
39
* [ Streams] ( #streams )
39
40
* [ Tasks] ( #tasks )
40
41
* [ Serial execution] ( #serial-execution )
@@ -44,6 +45,11 @@ testable.
44
45
The ` LockIsolated ` type helps wrap other values in an isolated context. It wraps the value in a
45
46
class with a lock, which allows you to read and write the value with a synchronous interface.
46
47
48
+ ### ` AnyHashableSendable `
49
+
50
+ The ` AnyHashableSendable ` type is a type-erased wrapper like ` AnyHashable ` that preserves the
51
+ sendability of the underlying value.
52
+
47
53
### Streams
48
54
49
55
The library comes with numerous helper APIs spread across the two Swift stream types:
Original file line number Diff line number Diff line change
1
+ /// A type-erased hashable, sendable value.
2
+ ///
3
+ /// A sendable version of `AnyHashable` that is useful in working around the limitation that an
4
+ /// existential `any Hashable` does not conform to `Hashable`.
5
+ public struct AnyHashableSendable : Hashable , Sendable {
6
+ public let base : any Hashable & Sendable
7
+
8
+ /// Creates a type-erased hashable, sendable value that wraps the given instance.
9
+ public init ( _ base: some Hashable & Sendable ) {
10
+ if let base = base as? AnyHashableSendable {
11
+ self = base
12
+ } else {
13
+ self . base = base
14
+ }
15
+ }
16
+
17
+ public static func == ( lhs: Self , rhs: Self ) -> Bool {
18
+ AnyHashable ( lhs. base) == AnyHashable ( rhs. base)
19
+ }
20
+
21
+ public func hash( into hasher: inout Hasher ) {
22
+ hasher. combine ( base)
23
+ }
24
+ }
25
+
26
+ extension AnyHashableSendable : CustomDebugStringConvertible {
27
+ public var debugDescription : String {
28
+ " AnyHashableSendable( " + String( reflecting: base) + " ) "
29
+ }
30
+ }
31
+
32
+ extension AnyHashableSendable : CustomReflectable {
33
+ public var customMirror : Mirror {
34
+ Mirror ( self , children: [ " value " : base] )
35
+ }
36
+ }
37
+
38
+ extension AnyHashableSendable : CustomStringConvertible {
39
+ public var description : String {
40
+ String ( describing: base)
41
+ }
42
+ }
Original file line number Diff line number Diff line change @@ -236,6 +236,7 @@ need to make weaker assertions due to non-determinism, but can still assert on s
236
236
### Data races
237
237
238
238
- `` LockIsolated ``
239
+ - `` AnyHashableSendable ``
239
240
240
241
### Serial execution
241
242
Original file line number Diff line number Diff line change
1
+ import ConcurrencyExtras
2
+ import XCTest
3
+
4
+ final class AnyHashableSendableTests : XCTestCase {
5
+ func testBasics( ) {
6
+ XCTAssertEqual ( AnyHashableSendable ( 1 ) , AnyHashableSendable ( 1 ) )
7
+ XCTAssertNotEqual ( AnyHashableSendable ( 1 ) , AnyHashableSendable ( 2 ) )
8
+
9
+ func make( _ base: some Hashable & Sendable ) -> AnyHashableSendable {
10
+ AnyHashableSendable ( base)
11
+ }
12
+
13
+ let flat = make ( 1 )
14
+ let nested = make ( flat)
15
+
16
+ XCTAssertEqual ( flat, nested)
17
+ }
18
+ }
You can’t perform that action at this time.
0 commit comments