-
-
Save couchdeveloper/b465d02d585d2564a7431deee70e2d42 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| struct Effect<Context: Sendable>: Identifiable { | |
| private var f: @Sendable (Context) async -> Void | |
| var id: UUID | |
| init(id: UUID, operation: @escaping @Sendable (Context) async -> Void) { | |
| self.id = id | |
| self.f = operation | |
| } | |
| func invoke(_ context: Context) async -> Void { | |
| await f(context) | |
| } | |
| } | |
| actor TestActor<State, Event> { | |
| private var state: State | |
| private let _send: (isolated TestActor, Event) -> Void | |
| private var a: [UUID: Task<Void, Never>] = [:] | |
| struct Proxy { | |
| weak var actor: TestActor? | |
| init(_ actor: TestActor? = nil) { | |
| self.actor = actor | |
| } | |
| func removeTask(with id: UUID) async { | |
| if var actor = actor { | |
| await Proxy.removeTask(with: id, actor: actor) | |
| } | |
| } | |
| private static func removeTask(with id: UUID, actor: isolated TestActor) { | |
| let task = actor.a.removeValue(forKey: id) | |
| task?.cancel() | |
| } | |
| } | |
| init( | |
| initialState: State, | |
| transform: @escaping @Sendable (inout State, Event) -> [Effect<TestActor.Proxy>] | |
| ) { | |
| self.state = initialState | |
| _send = { actor, event in | |
| actor.assertIsolated() | |
| let effects = transform(&actor.state, event) | |
| let proxy = Proxy(actor) | |
| effects.forEach { effect in | |
| let id = effect.id | |
| actor.a[id] = Task { | |
| actor.assertIsolated() | |
| await effect.invoke(proxy) | |
| await proxy.removeTask(with: id) | |
| } | |
| } | |
| } | |
| } | |
| func send(event: Event) { | |
| _send(self, event) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ideally, the actor should not depend on
a's type. That is, the initialisers would be in fact generic and would deduce the type ofafrom the typeEffect. For example, the key is set to typeUUID. However, an Effect might want to use any other hashable type. Or, suppose Effect does not conform toIdentifiableat all. In this case, the_send(_:)closure would not use a collection at all to manage the tasks, it would not even create a task to wrap the operation.So, making this available, it then would require, that
abecomes a local variable defined in the initialisers, only when needed and which get captured as var in the_send(_:)closure.