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

Unified Diff: mojo/dart/packages/mojo/lib/src/proxy.dart

Issue 2006093002: Dart: Futures -> Callbacks. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Merge Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/dart/packages/mojo/lib/src/control_message.dart ('k') | mojo/dart/packages/mojo/lib/src/stub.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/dart/packages/mojo/lib/src/proxy.dart
diff --git a/mojo/dart/packages/mojo/lib/src/proxy.dart b/mojo/dart/packages/mojo/lib/src/proxy.dart
index c0576b5ae25812da3be8a3d49a02bf3d7da17a83..7ca3644a76d14e7133fcb38ca3a0e725dcd7684e 100644
--- a/mojo/dart/packages/mojo/lib/src/proxy.dart
+++ b/mojo/dart/packages/mojo/lib/src/proxy.dart
@@ -69,7 +69,7 @@ abstract class ServiceConnector {
abstract class ProxyMessageHandler extends core.MojoEventHandler
implements MojoInterfaceControl {
- HashMap<int, Completer> _completerMap = new HashMap<int, Completer>();
+ HashMap<int, Function> _callbackMap = new HashMap<int, Function>();
Completer _errorCompleter = new Completer();
Set<Completer> _errorCompleters;
int _nextId = 0;
@@ -131,9 +131,8 @@ abstract class ProxyMessageHandler extends core.MojoEventHandler
@override
Future close({bool immediate: false}) {
- // Drop the completers for outstanding calls. The Futures will never
- // complete.
- _completerMap.clear();
+ // Drop the callbacks for outstanding calls. They will never be called.
+ _callbackMap.clear();
// Signal to any pending calls that the ProxyMessageHandler is closed.
if (_pendingCount > 0) {
@@ -160,11 +159,11 @@ abstract class ProxyMessageHandler extends core.MojoEventHandler
}
}
- Future sendMessageWithRequestId(Struct message, int name, int id, int flags) {
- var completer = new Completer();
+ void sendMessageWithRequestId(
+ Struct message, int name, int id, int flags, Function callback) {
if (!isBound) {
- proxyError("The ProxyMessageHandler is closed.");
- return completer.future;
+ proxyError("The Proxy is closed.");
+ return;
}
if (!isOpen) {
beginHandlingEvents();
@@ -179,16 +178,15 @@ abstract class ProxyMessageHandler extends core.MojoEventHandler
serviceMessage.handles);
if (endpoint.status == core.MojoResult.kOk) {
- _completerMap[id] = completer;
+ _callbackMap[id] = callback;
_pendingCount++;
} else {
proxyError("Write to message pipe endpoint failed: ${endpoint}");
}
- return completer.future;
}
// Need a getter for this for access in subclasses.
- HashMap<int, Completer> get completerMap => _completerMap;
+ HashMap<int, Function> get callbackMap => _callbackMap;
@override
String toString() {
@@ -198,15 +196,19 @@ abstract class ProxyMessageHandler extends core.MojoEventHandler
/// Queries the max version that the remote side supports.
/// Updates [version].
- Future<int> queryVersion() async {
+ Future<int> queryVersion() {
+ Completer<int> completer = new Completer<int>();
var params = new icm.RunMessageParams();
params.reserved0 = 16;
params.reserved1 = 0;
params.queryVersion = new icm.QueryVersion();
- var response = await sendMessageWithRequestId(
- params, icm.kRunMessageId, -1, MessageHeader.kMessageExpectsResponse);
- _version = response.queryVersionResult.version;
- return _version;
+ sendMessageWithRequestId(
+ params, icm.kRunMessageId, -1, MessageHeader.kMessageExpectsResponse,
+ (r0, r1, queryResult) {
+ _version = queryResult.version;
+ completer.complete(_version);
+ });
+ return completer.future;
}
/// If the remote side doesn't support the [requiredVersion], it will close
@@ -287,22 +289,119 @@ abstract class ProxyMessageHandler extends core.MojoEventHandler
"${message.header.type}");
return;
}
-
var response = icm.RunResponseMessageParams.deserialize(message.payload);
if (!message.header.hasRequestId) {
proxyError("Expected a message with a valid request Id.");
return;
}
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
+ Function callback = callbackMap[message.header.requestId];
+ if (callback == null) {
proxyError("Message had unknown request Id: ${message.header.requestId}");
return;
}
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Control message response completer already completed");
- return;
- }
- c.complete(response);
+ callbackMap.remove(message.header.requestId);
+ callback(
+ response.reserved0, response.reserved1, response.queryVersionResult);
+ return;
+ }
+}
+
+// A class that acts like a function, but which completes a completer with the
+// the result of the function rather than returning the result. E.g.:
+//
+// Completer c = new Completer();
+// var completerator = new Completerator._(c, f);
+// completerator(a, b);
+// await c.future;
+//
+// This completes the future c with the result of passing a and b to f.
+//
+// More usefully for Mojo, e.g.:
+// await _Completerator.completerate(
+// proxy.method, argList, MethodResponseParams#init);
+class _Completerator implements Function {
+ final Completer _c;
+ final Function _toComplete;
+
+ _Completerator._(this._c, this._toComplete);
+
+ static Future completerate(Function f, List args, Function ctor) {
+ Completer c = new Completer();
+ var newArgs = new List.from(args);
+ newArgs.add(new _Completerator._(c, ctor));
+ Function.apply(f, newArgs);
+ return c.future;
}
+
+ // Work-around to avoid checked-mode only having grudging support for
+ // Function implemented with noSuchMethod. See:
+ // https://github.com/dart-lang/sdk/issues/26528
+ dynamic call([
+ dynamic a1, dynamic a2, dynamic a3, dynamic a4, dynamic a5,
+ dynamic a6, dynamic a7, dynamic a8, dynamic a9, dynamic a10,
+ dynamic a11, dynamic a12, dynamic a13, dynamic a14, dynamic a15,
+ dynamic a16, dynamic a17, dynamic a18, dynamic a19, dynamic a20]);
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) =>
+ (invocation.memberName == #call)
+ ? _c.complete(Function.apply(_toComplete, invocation.positionalArguments))
+ : super.noSuchMethod(invocation);
+}
+
+/// Base class for Proxy class Futurizing wrappers. It turns callback-based
+/// methods on the Proxy into Future based methods in derived classes. E.g.:
+///
+/// class FuturizedHostResolverProxy extends FuturizedProxy<HostResolverProxy> {
+/// Map<Symbol, Function> _mojoMethods;
+///
+/// FuturizedHostResolverProxy(HostResolverProxy proxy) : super(proxy) {
+/// _mojoMethods = <Symbol, Function>{
+/// #getHostAddresses: proxy.getHostAddresses,
+/// };
+/// }
+/// Map<Symbol, Function> get mojoMethods => _mojoMethods;
+///
+/// FuturizedHostResolverProxy.unbound() :
+/// this(new HostResolverProxy.unbound());
+///
+/// static final Map<Symbol, Function> _mojoResponses = {
+/// #getHostAddresses: new HostResolverGetHostAddressesResponseParams#init,
+/// };
+/// Map<Symbol, Function> get mojoResponses => _mojoResponses;
+/// }
+///
+/// Then:
+///
+/// HostResolveProxy proxy = ...
+/// var futurizedProxy = new FuturizedHostResolverProxy(proxy);
+/// var response = await futurizedProxy.getHostAddresses(host, family);
+/// // etc.
+///
+/// Warning 1: The list of methods and return object constructors in
+/// FuturizedHostResolverProxy has to be kept up-do-date by hand with changes
+/// to the Mojo interface.
+///
+/// Warning 2: The recommended API to use is the generated callback-based API.
+/// This wrapper class is exposed only for convenience during development,
+/// and has no guarantee of optimal performance.
+abstract class FuturizedProxy<T extends Proxy> {
+ final T _proxy;
+ Map<Symbol, Function> get mojoMethods;
+ Map<Symbol, Function> get mojoResponses;
+
+ FuturizedProxy(T this._proxy);
+
+ T get proxy => _proxy;
+ Future responseOrError(Future f) => _proxy.responseOrError(f);
+ Future close({immediate: false}) => _proxy.close(immediate: immediate);
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) =>
+ mojoMethods.containsKey(invocation.memberName)
+ ? _Completerator.completerate(
+ mojoMethods[invocation.memberName],
+ invocation.positionalArguments,
+ mojoResponses[invocation.memberName])
+ : super.noSuchMethod(invocation);
}
« no previous file with comments | « mojo/dart/packages/mojo/lib/src/control_message.dart ('k') | mojo/dart/packages/mojo/lib/src/stub.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698