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

Unified 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: fixed comment Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: corelib/src/proxy.dart
diff --git a/corelib/src/proxy.dart b/corelib/src/proxy.dart
new file mode 100644
index 0000000000000000000000000000000000000000..873b3297c0d2003df2ee41d728950d0d3fbd3315
--- /dev/null
+++ b/corelib/src/proxy.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Base class for all RpcProxy's
Siggi Cherem (dart-lang) 2011/11/11 23:41:51 generally use the dart-doc style through-out (e.g.
+ *
+ * RpcProxy objects run in the "client" isolate and have a SendPort which
+ * they use to send messages to RpcReceiver objects running in a "service"
+ * isolate.
+ */
+
+class RpcProxy {
+ final Future<SendPort> futurePort;
Ben Laurie (Google) 2011/11/11 21:51:43 _futurePort?
+ RpcProxy(this.futurePort);
+
+ /**
+ * Called by derived classes to send a command through a SendPort to
+ * an RpcReceiver.
+ *
+ * parameters:
+ * command - String identifying what command to execute
+ * args - optional list of arguments to the command (this may contain other
+ * RpcProxy objects to refer to other target objects in the service
+ * isolate).
Ben Laurie (Google) 2011/11/11 21:51:43 How does that work? I don't see code to send RpcPr
mattsh 2011/11/11 22:16:02 Right. That's not in this CL yet, but plan to add
Siggi Cherem (dart-lang) 2011/11/11 23:41:51 is the purpose of this to establish a bi-direction
+ *
+ * returns:
+ * a Future object that will be set to the value that was
+ * received as a reply to the SendPort call.
+ */
+ Future sendCommand(String command, List args) {
+ Completer completer = new Completer();
+ futurePort.then((SendPort port) {
+ port.call({"command" : command, "args" : args}).receive((value, ignoreReplyTo) {
Siggi Cherem (dart-lang) 2011/11/11 23:41:51 80
+ assert(ignoreReplyTo === null);
+ value = _filterException(value);
+ if (value is Exception) {
+ completer.completeException(value);
+ } else {
+ completer.complete(value);
+ }
+ }
+ );
+ });
+ return completer.future;
+ }
+
+ // TODO (mattsh) hack, remove once we have serializable exceptions
+ Object _filterException(Object value) {
+ // Check if value is a serialized exception.
+ Exception e = RpcException.parse(value);
+ if (e != null) {
+ return e;
+ } else {
+ return value;
+ }
+ }
+}
+
+
+
+/**
+ * Base class for all Receivers
+ *
+ * RpcReceiver objects have a ReceivePort, where they receive commands (from
+ * RpcProxy objects) that they interpret and translate into method
+ * calls on a "target" object.
+ *
+ * All RpcReceiver derived classes must implement the [receiveCommand] abstract
+ * method (where they actually command messages and call
+ * appropriate methods on the target object).
+ *
+ */
+class RpcReceiver {
+
+ // static map of containing all receivers in this isolate. This is used
+ // to be able to find a receiver and target, given a SendPort.
+ static Map<SendPort, RpcReceiver> _receivers;
+ static _register(RpcReceiver receiver) {
+ if (_receivers == null) {
+ _receivers = new Map<SendPort, RpcReceiver>();
+ }
+ _receivers[receiver._receivePort.toSendPort()] = receiver;
+ }
+
+ static void closeAll() {
+ for (RpcReceiver receiver in _receivers.getValues()) {
+ receiver._receivePort.close();
+ }
+ }
+
+ // the port that this receiver will listen on
+ final ReceivePort _receivePort;
+
+ RpcReceiver(this._receivePort) {
+ // place this receiver in the receiver registry
+ _register(this);
+
+ // start listening on the receive port for command messages
+ _receivePort.receive((var message, SendPort replyTo) {
+ String command = message["command"];
+ List<Object> args = message["args"];
+
+ // Call the derived RpcReceiver to execute the command
+ // (if the command throws an exception, then catch the
+ // exception, serialize it, and send as the reply)
+ Object reply;
+ try {
+ reply = receiveCommand(message["command"], args);
+ } catch (Object e) {
+ reply = RpcException.format(e);
+ }
+
+ // send reply back to the proxy
+ replyTo.send(reply, null);
+ });
+ }
+
+ /**
+ * (implemented by derived classes).
+ *
+ * parameters -
+ * command - String identifying what command to execute
+ * on the target object
+ * args - list of arguments to the command (if any arguments
+ * were ReceivePorts, these have been translated to the
+ * corresponding target objects, so this List79 will not
+ * contain any ReceivePorts)
+ */
+ abstract Object receiveCommand(String command, List args);
+}
+
+// TODO - hack - need better way to serialize exceptions. For now
+// we take the message, and prefix with a recognizable string.
+class RpcException implements Exception {
+
+ static final String prefix = "RpcException:";
+
+ final String message;
+ const RpcException(this.message);
+
+ String toString() {
+ return message;
+ }
+
+ static String format(Exception e) {
+ return prefix + e.toString();
+ }
+
+ static RpcException parse(Object object) {
+ if (object === null || !(object is String)) {
+ return null;
+ }
+ String s = object;
+ if (!s.startsWith(prefix)) {
+ return null;
+ }
+ return new RpcException(s.substring(prefix.length, s.length));
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698