-
Notifications
You must be signed in to change notification settings - Fork 0
/
Receiver.swift
112 lines (103 loc) · 6.56 KB
/
Receiver.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//
// Receiver.swift
// Desolate
//
// Created by d-exclaimation on 12:43 PM.
// Copyright © 2021 d-exclaimation. All rights reserved.
//
import Foundation
///
// A diagram showing receiver pattern how perform returning values with callbacks between actors:
// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐
// │ Synchronous block │
// │ 5. Actor respond with a "message" using receiver │
// │ 6. Receiver ┌───────────────────────────────────────────────────────────┐ │
// │ give back ▼ │ │
// │ to actor ┌──────────┐ │ │
// │ ┌───────────────────┐ ┌──┤ Receiver │ ──────┐ 3. Give receiver ┌───────────────────────┼───┐ │
// │ │ │ │ └──────────┘ │ as "message" │ │ │ │
// │ │ .... ◄─┐ │ │ ▲ 2. Receiver │ to Desolate │ Isolation (async) │ │ │
// │ │ │ ┌─────┼─┘ │ made │ ┌───────────┐ │ │ │ │
// │ │ │ │ │ │ │ ▼ │ ▼ │ │ │ │
// │ │ │ ┌─┴──┴─────┼───────┴──┐ ┌────────┴─┐ ┌──────────┼──────────┐ │ │ │
// │ │ │ │ │ │ │ │ │ │ │ │ │
// │ │ └───►│ Actor2 Desolate │ │ Input │ │ Desolate Actor1 ├───────► .... │ │
// │ │ │ │ │ │ │ │ │ │ │ │
// │ │ └──────────┼──────────┘ └────┬─────┘ └──────────┼──────────┘ 4. Isolated │ │
// │ │ │ ▲ │ │ process │ │
// │ │ │ │ │ │ │ │
// │ │ Isolation (async) │ └─────────────────┘ │ │ │
// │ │ │ 1. Input ask for .ref │ │ │
// │ └───────────────────┘ └───────────────────────────┘ │
// │ │
// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘
///
/// Receiver class is any class that can given a value of a certain type with similar API to a Desolate, usually used for a request-response within Desolate used in something like `AskPattern` with `.ask`.
///
/// - Note: Receiver should not and aren't allowed to be instantiated on own its own.
/// - Attention: To make a Receiver, you are required to create a class that inherits and override all the methods
///
/// ### Making Receiver
///
/// - Using a Desolate `.ref`
/// ```
/// actor MyActor: AbstractDesolate, NonStop {
/// typealias MessageType = Int
/// ...
/// }
///
/// let actor = MyActor.new()
/// let receiver: Receiver<Int> = actor.ref
/// ```
///
/// - Inherit and Override with a custom class
/// ```
/// class MyLogger: Receiver<String> {
/// init() {}
///
/// override func tell(with msg: String) {
/// print(msg)
/// }
/// override func task(with msg: String) async {
/// print(msg)
/// }
/// }
///
/// let receiver: Receiver<String> = MyLogger()
/// ```
///
public class Receiver<ReceivedType> {
internal init() {}
/// Send a response message to the Actor referenced by this Receiver
///
/// - Parameter msg: Message to be sent
public func tell(with msg: ReceivedType) { fatalError("Receiver was never given a value") }
/// Asynchronously send a response message to the Actor referenced by this Receiver.
///
/// - Parameter msg: Message to be sent:
public func task(with msg: ReceivedType) async { fatalError("Receiver was never given a value") }
}
/// Receiver Wrapper for Desolate
internal class DesolateReceiver<ActorType: AbstractDesolate>: Receiver<ActorType.MessageType> {
/// inner actors of the reference
internal var innerActor: ActorType
public init(of ref: ActorType) {
innerActor = ref
}
/// Send a message to the Actor referenced by this Desolate
/// using `at-most-once` messaging semantics but doesn't wait for finished execution.
///
/// - Parameter msg: Message to be sent
public override func tell(with msg: ActorType.MessageType) {
Task.init { await innerActor.receive(msg) }
}
/// Asynchronously send a message to the Actor referenced by this Desolate using *at-most-once* messaging semantics.
///
/// - Parameter msg: Message to be sent:
public override func task(with msg: ActorType.MessageType) async {
let task = Task {
await innerActor.receive(msg)
}
await task.value
}
}