Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: tests/isolate/src/MintMakerRpcTest.dart

Issue 9363064: move proxy out into sample/proxy (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « samples/tests/samples/src/proxy/MintMakerRpcTest.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 /***
6 * Background:
7 *
8 * There are two "target" classes here that are the actual implementation
9 * of some service that performs some function. These "target" classes
10 * do not know about ports, isolates or rpc. They expose a local (usually
11 * synchronous) interface to perform some task. In this example, the "target"
12 * classes are very simple:
13 *
14 * Mint - creates new Purse objects with an initial amount of money
15 * Purse - holds an amount of money, and supports making deposits
16 * by taking money out of another purse.
17 *
18 * The point of this example is to show how to create a new Dart isolate
19 * and run Mint and Purse objects in that isolate, and communicate with
20 * these objects with a SendPort/ReceivePort message/reply conversation,
21 * where command arguments are marshalled and unmarshalled by RpcProxy and
22 * RpcReceiver objects.
23 *
24 * This example also shows:
25 * 1. how the messages in the conversation can refer to target
26 * objects besides the direct recipient of the message
27 * 2. how target objects can throw exceptions and these are propagated back
28 * through the SendPort/ReceivePort channel and back to the Future
29 * object that is waiting for the reply.
30 *
31 * Classes:
32 *
33 * Mint - used to create Purse objects
34 * Purse - holds a bank balance, supports depositing money from another Purse
35 * MintReceiver - listens on a ReceivePort and forwards commands to Mint
36 * PurseReceiver - listens on a ReceivePort and forwards commands to Purse
37 * MintProxy - sends commands to a SendPort (which is connected to a
38 * MintReceiver)
39 * PurseProxy - sends commands to a SendPort (which is connected to a
40 * PurseReceiver)
41 * MintIsolate - used to spawn a new Isolate and return the initial MintProxy
42 *
43 * Base classes used: (these are defined in proxy.dart)
44 * RpcReceiver - MintReceiver and PurseReceiver derive from RpcReceiver to
45 * get behavior common to all Receivers.
46 * RpcProxy - MintProxy and PurseProxy derive from RpcProxy to get behavior
47 * common to all proxies
48 *
49 * Explanation:
50 *
51 * We make a "receiver" object (MintReceiver and PurseReceiver) for each
52 * target object that is being exposed. Each "receiver" object gets
53 * its own ReceivePort, where it listen for messages that it interprets
54 * as commands for its target object.
55 *
56 * When a command is received by a receiver, the receiver calls the appropriate
57 * method on the the target object. The receiver object runs in the same
58 * isolate as its target object. This isolate is called the "service" isolate.
59 *
60 * RpcProxy objects run in the "client" isolate. Each proxy object has a
61 * SendPort which is connected to the ReceivePort of a corresponding receiver
62 * object.
63 *
64 * So, a MintProxy object (running in the "client" isolate) is connected
65 * to a MintReceiver object (running in the "service" isolate) which is
66 * connected to a Mint target object (also running in the "service" isolate).
67 *
68 * Startup/Shutdown:
69 *
70 * The MintIsolate has a method open that spawns a new isolate and returns
71 * a MintProxy object.
72 *
73 * To shut down the MintIsolate, call 'close' on the MintProxy object. This
74 * will close all receive ports of all receivers in the isolate, which will
75 * cause the mint isolate to shutdown.
76 */
77
78 class Mint {
79 Mint();
80 Purse createPurse(int initialBalance) {
81 return new Purse(initialBalance);
82 }
83 }
84
85 class Purse {
86 int _balance;
87
88 Purse(this._balance) {}
89
90 int queryBalance() {
91 return _balance;
92 }
93
94 int deposit(int amount, Purse source) {
95 if (source._balance < amount) {
96 throw "OverdraftException";
97 }
98 source._balance -= amount;
99 _balance += amount;
100 return _balance;
101 }
102 }
103
104
105 class MintProxy extends RpcProxy {
106 MintProxy(Future<SendPort> sendPort) : super(sendPort) { }
107 Future<PurseProxy> createPurse(int initialBalance) {
108 return sendCommand("createPurse", [initialBalance], (sendPort) {
109 Completer<SendPort> completer = new Completer();
110 completer.complete(sendPort);
111 return new PurseProxy(completer.future);
112 });
113 }
114 Future<String> close() {
115 return sendCommand("close", null, null);
116 }
117 }
118
119 class MintReceiver extends RpcReceiver<Mint> {
120 MintReceiver(ReceivePort receivePort) : super(new Mint(), receivePort) {}
121 Object receiveCommand(String command, List args) {
122 switch(command) {
123 case "createPurse":
124 int balance = args[0];
125 Purse purse = target.createPurse(balance);
126 return new PurseReceiver(purse, new ReceivePort());
127 case "close":
128 RpcReceiver.closeAll();
129 return "close command processed";
130 default:
131 throw "MintReceiver unrecognized command";
132 }
133 }
134 }
135
136 class PurseProxy extends RpcProxy {
137 PurseProxy(Future<SendPort> sendPort) : super(sendPort) { }
138 Future<int> queryBalance() {
139 return sendCommand("queryBalance", null, null);
140 }
141 Future<int> deposit(int amount, PurseProxy from) {
142 return sendCommand("deposit", [amount, from], null);
143 }
144 }
145
146 class PurseReceiver extends RpcReceiver<Purse> {
147
148 PurseReceiver(Purse purse, ReceivePort receivePort) : super(purse, receivePort ) {}
149
150 Object receiveCommand(String command, List args) {
151 switch(command) {
152 case "queryBalance":
153 return target.queryBalance();
154 case "deposit":
155 int amount = args[0];
156 Purse fromPurse = args[1];
157 return target.deposit(amount, fromPurse);
158 default:
159 throw "PurseReceiver unrecognized command";
160 }
161 }
162 }
163
164 class MintIsolate extends Isolate {
165 MintIsolate() : super.light() {}
166
167 MintProxy open() {
168 return new MintProxy(spawn());
169 }
170
171 void main() {
172 ReceivePort receivePort = port;
173 new MintReceiver(receivePort);
174 }
175 }
176
177 class MintTest {
178 static void testMain() {
179 print("starting test");
180 MintProxy mint = new MintIsolate().open();
181 mint.createPurse(100).then((PurseProxy purse1) {
182 purse1.queryBalance().then((int balance) {
183 Expect.equals(100, balance);
184 mint.createPurse(0).then((PurseProxy purse2) {
185 purse2.queryBalance().then((int balance) {
186 Expect.equals(0, balance);
187 purse2.deposit(5, purse1).then((int newBalance) {
188 Expect.equals(0 + 5, newBalance);
189 purse1.queryBalance().then((int balance) {
190 Expect.equals(100 - 5, balance);
191 });
192 purse2.deposit(42, purse1).then((int newBalance) {
193 int balance2 = newBalance;
194 Expect.equals(0 + 5 + 42, balance2);
195 purse1.queryBalance().then((int balance) {
196 int balance1 = balance;
197 Expect.equals(100 - 5 - 42, balance);
198 // Now try to deposit more money into purse1 than
199 // is currently in purse2. Make sure we get an exception
200 // doing this.
201 Future<int> badBalance = purse1.deposit(1000, purse2);
202 badBalance.then((int newBalance) {
203 // Should never arrive here because there are
204 // insufficient funds to actually do the deposit
205 Expect.fail("did not detect overdraft");
206 });
207 badBalance.handleException((Object exception) {
208 if (exception.toString().contains(
209 "OverdraftException", 0)) {
210 print("Correctly detected overdraft.");
211 // Check that the balance in each purse is unchanged from
212 // before we attempted to do the overdraft.
213 purse1.queryBalance().then((int balance) {
214 Expect.equals(balance, balance1);
215 purse2.queryBalance().then((int balance) {
216 Expect.equals(balance, balance2);
217 // OK, we're all done now, close down the mint isolate
218 mint.close().then((reply) {
219 print(reply);
220 });
221 });
222 });
223 return true;
224 } else {
225 return false;
226 }
227 });
228 });
229 });
230 });
231 });
232 });
233 });
234 });
235 print ("exit main");
236 }
237 }
238
239 main() {
240 MintTest.testMain();
241 }
OLDNEW
« no previous file with comments | « samples/tests/samples/src/proxy/MintMakerRpcTest.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698