-
Notifications
You must be signed in to change notification settings - Fork 1
/
Program.cs
177 lines (132 loc) · 6.31 KB
/
Program.cs
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.Threading.Tasks;
using ActorFramework;
using ActorInterface;
using ActorTestingFramework;
using TypedActorFramework;
using TypedActorInterface;
namespace Example
{
internal class Program
{
private static void Main(string[] args)
{
IActorRuntime runtime = new SimpleActorRuntime();
Task mainTask = runtime.StartMain(() =>
{
// Normal actors.
// Creates an actor and yields its mailbox.
// Only the owner of a mailbox can call Receive.
// Any actor can Send to a mailbox.
// Every actor has its own mailbox that stores objects.
IMailbox<object> helloActorMailbox =
runtime.Create(() =>
{
IMailbox<object> myMailbox = runtime.CurrentMailbox();
object msg = myMailbox.Receive();
Console.WriteLine(msg);
msg = myMailbox.Receive();
Console.WriteLine(msg);
IMailbox<string> mailbox =
(IMailbox<string>) myMailbox.Receive();
mailbox.Send("message for separate mailbox");
Console.WriteLine(
$"I am actor with mailbox {myMailbox} and I am about to terminate.");
return 1;
});
helloActorMailbox.Send("hello");
helloActorMailbox.Send("world");
// Creates another (separate) mailbox for the current actor.
// The main mailbox of the current actor is not used in this example.
// Additional mailboxes can have a more specific type parameter than object.
IMailbox<string> separateMailbox =
runtime.CreateMailbox<string>();
// send it to helloActor
helloActorMailbox.Send(separateMailbox);
// receive a string on this separate mailbox (no casting)
string textResult = separateMailbox.Receive();
Console.WriteLine(textResult);
// Typed actors.
// Built on top of IActorRuntime
// (which could be implemented in many ways).
ITypedActorRuntime typedRuntime =
new SimpleTypedActorRuntime(runtime);
// Create a typed actor: answerPhone is a proxy object.
// The proxy class for IAnswerPhone is generated dynamically (once)
// at runtime using System.Reflection.Emit.
IAnswerPhone answerPhone =
typedRuntime.Create<IAnswerPhone>(new AnswerPhone());
IPhoner phoner1 = typedRuntime.Create<IPhoner>(new Phoner());
IPhoner phoner2 = typedRuntime.Create<IPhoner>(new Phoner());
// Send messages to the actors by invoking methods.
phoner1.Init(1, answerPhone);
phoner2.Init(2, answerPhone);
phoner2.Go();
phoner1.Go();
// We can use a (lower level) additional mailbox to receive results.
IMailbox<string> returnMailbox = runtime.CreateMailbox<string>();
answerPhone.CheckMessages(returnMailbox);
Console.WriteLine(returnMailbox.Receive());
// Or we can call methods that return a value, which
// is similar to the above (current actor is blocked).
// Methods with a return value can also have `out` and `ref` parameters.
int b;
string res = answerPhone.CheckMessagesSync(55, out b, "temp");
Console.WriteLine(res);
Console.WriteLine($"b is {b}"); // Should be 3
// If a method with a return type throws an exception
// (when executing on another actor), the exception is
// sent back to us (the caller) and thrown.
b = 0;
try
{
res = answerPhone.CheckMessagesSync(56, out b, "temp");
}
catch (ArgumentException ex)
{
// The stack trace includes the stack frames from the
// other actor.
Console.WriteLine(ex);
Console.WriteLine($"b is {b}"); // Should be 3
}
});
mainTask.Wait();
// Random testing (can use actors or typed actors).
// Do 100 executions of the test case below.
ITestLauncher testLauncher = new TestLauncher();
testLauncher.SetScheduler(new RandomScheduler(0));
for (int i = 1; i <= 100; ++i)
{
Console.WriteLine("\n\n... ITERATION " + i + "\n\n");
testLauncher.Execute((runtime2, testingRuntime) =>
{
IMailbox<object> helloActorMailbox =
runtime2.Create(() =>
{
IMailbox<object> myMailbox =
runtime2.CurrentMailbox();
object msg = myMailbox.Receive();
Console.WriteLine(msg);
msg = myMailbox.Receive();
Console.WriteLine(msg);
IMailbox<string> mailbox =
(IMailbox<string>) myMailbox.Receive();
mailbox.Send("message for separate mailbox");
Console.WriteLine(
$"I am actor with mailbox {myMailbox} and I am about to terminate.");
return 1;
});
helloActorMailbox.Send("hello");
helloActorMailbox.Send("world");
IMailbox<string> separateMailbox =
runtime2.CreateMailbox<string>();
helloActorMailbox.Send(separateMailbox);
Console.WriteLine(separateMailbox.Receive());
});
}
Console.WriteLine("[Done]");
Console.ReadLine();
}
}
}