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

Side by Side Diff: corelib/src/proxy.dart

Issue 8536006: rpc example for directory file listing (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: builtin_in.cc Created 9 years 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
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 * Base class for all RpcProxy's
7 *
8 * RpcProxy objects run in the "client" isolate and have a SendPort which
9 * they use to send messages to RpcReceiver objects running in a "service"
10 * isolate.
11 */
12
13 class RpcProxy {
14 final Future<SendPort> futurePort;
15 RpcProxy(Future<SendPort> this.futurePort) {}
16
17 /**
18 * Called by derived classes to send a command through a SendPort to
19 * an RpcReceiver.
20 *
21 * parameters:
22 * command - String identifying what command to execute
23 * args - optional list of arguments to the command (this may contain other
24 * RpcProxy objects to refer to other target objects in the service
25 * isolate).
26 *
27 * returns:
28 * a Future object that will be set to the value that was
29 * received as a reply to the SendPort call.
30 */
31 Future sendCommand(String command, List args, adjustReply(Object value)) {
32 Completer completer = new Completer();
33 futurePort.then((SendPort port) {
34 args = _filterArgs(args);
35 port.call({"command" : command, "args" : args}).receive(
36 (value, ignoreReplyTo) {
37 assert(ignoreReplyTo === null);
38 value = _filterException(value);
39 if (adjustReply != null) {
40 // give derived proxy class a chance to transate SendPort to
41 // RpcProxy
42 value = adjustReply(value);
43 }
44 if (value is Exception) {
45 completer.completeException(value);
46 } else {
47 completer.complete(value);
48 }
49 }
50 );
51 });
52 return completer.future;
53 }
54
55 /**
56 * Convert RpcProxy objects to SendPorts
Siggi Cherem (dart-lang) 2011/11/30 01:44:38 style nits: - use single line /** ... */ for comme
mattsh 2011/11/30 05:03:33 Done.
57 */
58 static List _filterArgs(List args) {
59 if (args == null) {
60 return null;
61 }
62 List filtered = new List();
63 for (Object arg in args) {
64 if (arg is RpcProxy) {
65 RpcProxy proxy = arg;
66 // TODO - need to figure out if/how to wait for proxy's
67 // port to be ready
68 filtered.add(proxy.futurePort.value);
69 } else {
70 filtered.add(arg);
71 }
72 }
73 return filtered;
74 }
75
76 // TODO (mattsh) hack, remove once we have serializable exceptions
77 Object _filterException(Object value) {
78 // Check if value is a serialized exception.
79 Exception e = RpcException.parse(value);
80 if (e != null) {
81 return e;
82 } else {
83 return value;
84 }
85 }
86 }
87
88
89
90 /**
91 * Base class for all Receivers
92 *
93 * RpcReceiver objects have a ReceivePort, where they receive commands (from
94 * RpcProxy objects) that they interpret and translate into method
95 * calls on a "target" object.
96 *
97 * All RpcReceiver derived classes must implement the [receiveCommand] abstract
98 * method (where they actually command messages and call
99 * appropriate methods on the target object).
100 *
101 * type parameters:
102 * T - the type of the target object that this a receiver for
103 */
104 class RpcReceiver<T> {
105
106 // static map of containing all receivers in this isolate. This is used
107 // to be able to find a receiver and target, given a SendPort.
108 static Map<SendPort, RpcReceiver> _receivers;
109 static _register(RpcReceiver receiver) {
110 if (_receivers == null) {
111 _receivers = new Map<SendPort, RpcReceiver>();
112 }
113 _receivers[receiver._receivePort.toSendPort()] = receiver;
114 }
115
116 static void closeAll() {
117 for (RpcReceiver receiver in _receivers.getValues()) {
118 receiver._receivePort.close();
119 }
120 }
121
122 // the port that this receiver will listen on
Siggi Cherem (dart-lang) 2011/11/30 01:44:38 (nit): to be consistent with all of our libraries,
Siggi Cherem (dart-lang) 2011/11/30 01:46:45 (here and elsewhere in this code)
mattsh 2011/11/30 05:03:33 Done.
mattsh 2011/11/30 05:03:33 Done.
123 final ReceivePort _receivePort;
124
125 // the "target" object that this RpcReceiver will be calling
126 // to actually do some work.
127 final T target;
128
129 RpcReceiver(T this.target, ReceivePort this._receivePort) {
130 // place this receiver in the receiver registry
131 _register(this);
132
133 // start listening on the receive port for command messages
134 _receivePort.receive((var message, SendPort replyTo) {
135 String command = message["command"];
136
137 // filter incoming arguments (looking for SendPorts
138 // that we need to translate to RpcReceiver objects)
139 List args = _filterIncomingArgs(message["args"]);
140
141 // Call the derived RpcReceiver to execute the command
142 // (if the command throws an exception, then catch the
143 // exception, serialize it, and send as the reply)
144 Object reply;
145 try {
146 reply = receiveCommand(message["command"], args);
147 } catch (var e) {
148 // TODO(mattsh) - would really prefer to catch Object, but currently
149 // bug http://code.google.com/p/dart/issues/detail?id=469
150 reply = RpcException.format(e);
151 }
152
153 reply = _filterReply(reply);
154
155 // send reply back to the proxy
156 replyTo.send(reply, null);
157 });
158 }
159
160 /**
161 * Translate any ReceivePort objects in the arguments to
162 * the corresponding target object.
163 */
164 static List _filterIncomingArgs(List originalArgs) {
165 List args = new List();
166 var i = 0;
167 if (originalArgs != null) {
168 for (var arg in originalArgs) {
169 if (arg is SendPort) {
170 if (_receivers[arg] == null) {
171 throw "can't find receiver for SendPort";
172 }
173 arg = _receivers[arg].target;
174 if (arg == null) {
175 throw "receiver is missing target";
176 }
177 }
178 args.add(arg);
179 i++;
180 }
181 }
182 return args;
183 }
184
185 /**
186 * Walk over the reply that this receiver is about to send
187 * back, and:
188 * 1. translate RpcReceiver objects in the reply to the corresponding
189 * ReceivePort.
Siggi Cherem (dart-lang) 2011/11/30 01:44:38 nit: is there a 2. ?, remove the bullet list?
mattsh 2011/11/30 05:03:33 Done.
190 *
191 * TODO(mattsh) need to walk deeply
Siggi Cherem (dart-lang) 2011/11/30 01:46:45 TODO's shouldn't be inside the /** */ docs, so tha
mattsh 2011/11/30 05:03:33 Done.
192 */
193 static _filterReply(Object reply) {
194 if (reply is RpcReceiver) {
195 RpcReceiver receiver = reply;
196 reply = receiver._receivePort.toSendPort();
197 }
198 return reply;
199 }
200
201 /**
202 * (implemented by derived classes).
203 *
204 * parameters -
205 * command - String identifying what command to execute
206 * on the target object
207 * args - list of arguments to the command (if any arguments
208 * were ReceivePorts, these have been translated to the
209 * corresponding target objects, so this List79 will not
210 * contain any ReceivePorts)
211 */
212 abstract Object receiveCommand(String command, List args);
213 }
214
215 // TODO - hack - need better way to serialize exceptions. For now
Siggi Cherem (dart-lang) 2011/11/30 01:44:38 TODO(mattsh)? no need to say 'hack'
mattsh 2011/11/30 05:03:33 Done.
216 // we take the message, and prefix with a recognizable string.
217 class RpcException implements Exception {
218
219 static final String prefix = "RpcException:";
220
221 final String message;
222 const RpcException(String this.message);
223
224 String toString() {
225 return message;
226 }
227
228 static String format(Exception e) {
229 return prefix + e.toString();
230 }
231
232 static RpcException parse(Object object) {
233 if (object === null || !(object is String)) {
234 return null;
235 }
236 String s = object;
237 if (!s.startsWith(prefix)) {
238 return null;
239 }
240 return new RpcException(s.substring(prefix.length, s.length));
241 }
242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698