OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Things that should be "auto-generated" are between AUTO START and | |
6 // AUTO END (or just AUTO if it's a single line). | |
7 | |
8 #library("MintMakerTest"); | |
9 #import("dart:isolate"); | |
10 #import('../../../lib/unittest/unittest.dart'); | |
11 | |
12 class Mint { | |
13 Mint() : registry_ = new Map<SendPort, Purse>() { | |
14 // AUTO START | |
15 ReceivePort mintPort = new ReceivePort(); | |
16 port = mintPort.toSendPort(); | |
17 serveMint(mintPort); | |
18 // AUTO END | |
19 } | |
20 | |
21 // AUTO START | |
22 void serveMint(ReceivePort port) { | |
23 port.receive((var message, SendPort replyTo) { | |
24 int balance = message; | |
25 Purse purse = createPurse(balance); | |
26 replyTo.send([ purse.port ], null); | |
27 }); | |
28 } | |
29 // AUTO END | |
30 | |
31 Purse createPurse(int balance) { | |
32 Purse purse = new Purse(this, balance); | |
33 registry_[purse.port] = purse; | |
34 return purse; | |
35 } | |
36 | |
37 Purse lookupPurse(SendPort port) { | |
38 return registry_[port]; | |
39 } | |
40 | |
41 Map<SendPort, Purse> registry_; | |
42 // AUTO | |
43 SendPort port; | |
44 } | |
45 | |
46 | |
47 // AUTO START | |
48 class MintWrapper { | |
49 MintWrapper(SendPort this.mint_) {} | |
50 | |
51 void createPurse(int balance, handlePurse(PurseWrapper purse)) { | |
52 mint_.call(balance).then((var message) { | |
53 SendPort purse = message[0]; | |
54 handlePurse(new PurseWrapper(purse)); | |
55 }); | |
56 } | |
57 | |
58 SendPort mint_; | |
59 } | |
60 // AUTO END | |
61 | |
62 | |
63 /* | |
64 One way this could look without the autogenerated code: | |
65 | |
66 class Mint { | |
67 Mint() : registry_ = new Map<SendPort, Purse>() { | |
68 } | |
69 | |
70 wrap Purse createPurse(int balance) { | |
71 Purse purse = new Purse(this, balance); | |
72 registry_[purse.port] = purse; | |
73 return purse; | |
74 } | |
75 | |
76 Purse lookupPurse(SendPort port) { | |
77 return registry_[port]; | |
78 } | |
79 | |
80 Map<SendPort, Purse> registry_; | |
81 } | |
82 | |
83 The other end of the port would use Wrapper<Mint> as the wrapper, or | |
84 Future<Mint> as a future for the wrapper. | |
85 */ | |
86 | |
87 | |
88 class Purse { | |
89 Purse(Mint this.mint, int this.balance) { | |
90 // AUTO START | |
91 ReceivePort recipient = new ReceivePort(); | |
92 port = recipient.toSendPort(); | |
93 servePurse(recipient); | |
94 // AUTO END | |
95 } | |
96 | |
97 // AUTO START | |
98 void servePurse(ReceivePort recipient) { | |
99 recipient.receive((var message, SendPort replyTo) { | |
100 String command = message[0]; | |
101 if (command == "balance") { | |
102 replyTo.send(queryBalance(), null); | |
103 } else if (command == "deposit") { | |
104 Purse source = mint.lookupPurse(message[2]); | |
105 deposit(message[1], source); | |
106 } else if (command == "sprout") { | |
107 Purse result = sproutPurse(); | |
108 replyTo.send([ result.port ], null); | |
109 } else { | |
110 // TODO: Send an exception back. | |
111 replyTo.send("Exception: Command not understood", null); | |
112 } | |
113 }); | |
114 } | |
115 // AUTO END | |
116 | |
117 int queryBalance() { return balance; } | |
118 | |
119 Purse sproutPurse() { return mint.createPurse(0); } | |
120 | |
121 void deposit(int amount, Purse source) { | |
122 // TODO: Throw an exception if the source purse doesn't hold | |
123 // enough dough. | |
124 balance += amount; | |
125 source.balance -= amount; | |
126 } | |
127 | |
128 Mint mint; | |
129 int balance; | |
130 // AUTO | |
131 SendPort port; | |
132 } | |
133 | |
134 | |
135 // AUTO START | |
136 class PurseWrapper { | |
137 PurseWrapper(SendPort this.purse_) {} | |
138 | |
139 void queryBalance(handleBalance(int balance)) { | |
140 purse_.call([ "balance" ]).then((var message) { | |
141 int balance = message; | |
142 handleBalance(balance); | |
143 }); | |
144 } | |
145 | |
146 void sproutPurse(handleSprouted(PurseWrapper sprouted)) { | |
147 purse_.call([ "sprout" ]).then((var message) { | |
148 SendPort sprouted = message[0]; | |
149 handleSprouted(new PurseWrapper(sprouted)); | |
150 }); | |
151 } | |
152 | |
153 void deposit(PurseWrapper source, int amount) { | |
154 purse_.send([ "deposit", amount, source.purse_ ], null); | |
155 } | |
156 | |
157 | |
158 SendPort purse_; | |
159 } | |
160 // AUTO END | |
161 | |
162 | |
163 // AUTO STATUS UNCLEAR! | |
164 | |
165 class MintMakerWrapperIsolate extends Isolate { | |
166 MintMakerWrapperIsolate() : super() { } | |
167 void main() { | |
168 this.port.receive((var message, SendPort replyTo) { | |
169 Mint mint = new Mint(); | |
170 replyTo.send([ mint.port ], null); | |
171 }); | |
172 } | |
173 } | |
174 | |
175 class MintMakerWrapper { | |
176 MintMakerWrapper() { | |
177 port_ = new MintMakerWrapperIsolate().spawn(); | |
178 } | |
179 | |
180 void makeMint(handleMint(MintWrapper mint)) { | |
181 port_.then((SendPort port) { | |
182 port.call(null).then((var message) { | |
183 SendPort mint = message[0]; | |
184 handleMint(new MintWrapper(mint)); | |
185 }); | |
186 }); | |
187 } | |
188 | |
189 Future<SendPort> port_; | |
190 } | |
191 | |
192 _checkBalance(PurseWrapper wrapper, expected) { | |
193 wrapper.queryBalance(expectAsync1((int balance) { | |
194 expect(balance).equals(expected); | |
195 })); | |
196 } | |
197 | |
198 main() { | |
199 test("creating purse, deposit, and query balance", () { | |
200 MintMakerWrapper mintMaker = new MintMakerWrapper(); | |
201 mintMaker.makeMint(expectAsync1((MintWrapper mint) { | |
202 mint.createPurse(100, expectAsync1((PurseWrapper purse) { | |
203 _checkBalance(purse, 100); | |
204 purse.sproutPurse(expectAsync1((PurseWrapper sprouted) { | |
205 _checkBalance(sprouted, 0); | |
206 _checkBalance(purse, 100); | |
207 | |
208 sprouted.deposit(purse, 5); | |
209 _checkBalance(sprouted, 0 + 5); | |
210 _checkBalance(purse, 100 - 5); | |
211 | |
212 sprouted.deposit(purse, 42); | |
213 _checkBalance(sprouted, 0 + 5 + 42); | |
214 _checkBalance(purse, 100 - 5 - 42); | |
215 })); | |
216 })); | |
217 })); | |
218 }); | |
219 | |
220 /* This is an attempt to show how the above code could look like if we had | |
221 * better language support for asynchronous messages (deferred/asynccall). | |
222 * The static helper methods like createPurse and queryBalance would also | |
223 * have to be marked async. | |
224 | |
225 void run(port) { | |
226 MintMakerWrapper mintMaker = spawnMintMaker(); | |
227 deferred { | |
228 MintWrapper mint = asynccall mintMaker.createMint(); | |
229 PurseWrapper purse = asynccall mint.createPurse(100); | |
230 Expect.equals(100, asynccall purse.queryBalance()); | |
231 | |
232 PurseWrapper sprouted = asynccall purse.sproutPurse(); | |
233 Expect.equals(0, asynccall sprouted.queryBalance()); | |
234 | |
235 asynccall sprouted.deposit(purse, 5); | |
236 Expect.equals(0 + 5, asynccall sprouted.queryBalance()); | |
237 Expect.equals(100 - 5, asynccall purse.queryBalance()); | |
238 | |
239 asynccall sprouted.deposit(purse, 42); | |
240 Expect.equals(0 + 5 + 42, asynccall sprouted.queryBalance()); | |
241 Expect.equals(100 - 5 - 42, asynccall purse.queryBalance()); | |
242 } | |
243 } | |
244 */ | |
245 | |
246 /* And a version using futures and wrappers. | |
247 | |
248 void run(port) { | |
249 Wrapper<MintMaker> mintMaker = spawnMintMaker(); | |
250 Future<Mint> mint = mintMaker...createMint(); | |
251 Future<Purse> purse = mint...createPurse(100); | |
252 Expect.equals(100, purse.queryBalance()); | |
253 | |
254 Future<Purse> sprouted = purse...sproutPurse(); | |
255 Expect.equals(0, sprouted.queryBalance()); | |
256 | |
257 sprouted...deposit(purse, 5); | |
258 Expect.equals(0 + 5, sprouted.queryBalance()); | |
259 Expect.equals(100 - 5, purse.queryBalance()); | |
260 | |
261 sprouted...deposit(purse, 42); | |
262 Expect.equals(0 + 5 + 42, sprouted.queryBalance()); | |
263 Expect.equals(100 - 5 - 42, purse.queryBalance()); | |
264 } | |
265 */ | |
266 } | |
OLD | NEW |