| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Dart core library. | 5 /** A library to illustrate pipelining. */ |
| 6 #library("promise"); |
| 7 |
| 8 /** A promise to value of type [T] that may be computed asynchronously. */ |
| 9 // TODO(sigmund,benl): remove Promise<T> use Future<T> instead. |
| 10 interface Promise<T> default PromiseImpl<T> { |
| 11 |
| 12 Promise(); |
| 13 |
| 14 /** A promise that already has a computed value. */ |
| 15 Promise.fromValue(T value); |
| 16 |
| 17 /** |
| 18 * The value once it is computed. It will be null when the promise is in |
| 19 * progress ([:!isDone():]), when it was cancelled ([:isCancelled():]), or |
| 20 * when the computed value is actually null. |
| 21 */ |
| 22 T get value(); |
| 23 |
| 24 /** |
| 25 * Provide the computed value; throws an exception if a value has already been |
| 26 * provided or the promise previously completed with an error; ignored if the |
| 27 * promise was cancelled. |
| 28 */ |
| 29 void complete(T value); |
| 30 |
| 31 /** Error that occurred while computing the value, if any; null otherwise. */ |
| 32 get error(); |
| 33 |
| 34 /** Indicate that an error was found while computing this value. */ |
| 35 void fail(var error); |
| 36 |
| 37 /** Whether the asynchronous work is done (normally or with errors). */ |
| 38 bool isDone(); |
| 39 |
| 40 /** Whether the work represented by this promise has been cancelled. */ |
| 41 bool isCancelled(); |
| 42 |
| 43 /** Whether the work represented by this promise has computed a value. */ |
| 44 bool hasValue(); |
| 45 |
| 46 /** Whether the work represented by this promise has finished in an error. */ |
| 47 bool hasError(); |
| 48 |
| 49 /** Cancel the asynchronous work of this promise, if possible. */ |
| 50 bool cancel(); |
| 51 |
| 52 /** Register a normal continuation to execute when the value is available. */ |
| 53 void addCompleteHandler(void completeHandler(T result)); |
| 54 |
| 55 /** Register an error continuation to execute if an error is found. */ |
| 56 void addErrorHandler(void errorHandler(var error)); |
| 57 |
| 58 /** Register a handler to execute when [cancel] is called. */ |
| 59 void addCancelHandler(void cancelHandler()); |
| 60 |
| 61 /** |
| 62 * When this promise completes, execute [callback]. The result of [callback] |
| 63 * will be exposed through the returned promise. This promise, and the |
| 64 * resulting promise (r) are connected as follows: |
| 65 * - this.complete --> r.complete (with the result of [callback]) |
| 66 * - this.error --> r.error (the same error is propagated to r) |
| 67 * - this.cancel --> r.error (the cancellation is shown as an error to r) |
| 68 * - r.cancel --> this continues executing regardless |
| 69 */ |
| 70 Promise then(callback(T value)); |
| 71 |
| 72 /** |
| 73 * Converts this promise so that its result is a non-promise value. For |
| 74 * instance, if this promise is of type Promise<Promise<Promise<T>>>, |
| 75 * flatten returns a Promise<T>. |
| 76 */ |
| 77 Promise flatten(); |
| 78 |
| 79 /** |
| 80 * Mark this promise as complete when some or all values in [arr] are |
| 81 * computed. Every time one of the promises is computed, it is passed to |
| 82 * [joinDone]. When [joinDone] returns true, this instance is marked as |
| 83 * complete with the last value that was computed. |
| 84 */ |
| 85 void join(Collection<Promise> arr, bool joinDone(Promise completed)); |
| 86 |
| 87 /** |
| 88 * Mark this promise as complete when [n] promises in [arr] complete, then |
| 89 * cancel the rest of the promises in [arr] that didn't complete. |
| 90 */ |
| 91 void waitFor(Collection<Promise> arr, int n); |
| 92 } |
| 93 |
| 94 |
| 95 interface Proxy extends Promise<bool> default ProxyImpl { |
| 96 |
| 97 Proxy.forPort(SendPort port); |
| 98 Proxy.forIsolate(Isolate isolate); |
| 99 Proxy._forIsolateWithPromise(Isolate isolate, Promise<SendPort> promise); |
| 100 /* |
| 101 * The [Proxy.forReply] constructor is used to create a proxy for |
| 102 * the object that will be the reply to a message send. |
| 103 */ |
| 104 Proxy.forReply(Promise<SendPort> port); |
| 105 |
| 106 void send(List message); |
| 107 Promise call(List message); |
| 108 |
| 109 } |
| 110 |
| 111 |
| 112 class ProxyImpl extends ProxyBase implements Proxy { |
| 113 |
| 114 ProxyImpl.forPort(SendPort port) |
| 115 : super.forPort(port) { } |
| 116 |
| 117 ProxyImpl.forIsolate(Isolate isolate) |
| 118 : this._forIsolateWithPromise(isolate, new Promise<SendPort>()); |
| 119 |
| 120 ProxyImpl._forIsolateWithPromise(Isolate isolate, Promise<SendPort> promise) |
| 121 // TODO(floitsch): it seems wrong to call super.forReply here. |
| 122 : super.forReply(promise) { |
| 123 isolate.spawn().then((SendPort port) { |
| 124 promise.complete(port); |
| 125 }); |
| 126 } |
| 127 |
| 128 /* |
| 129 * The [Proxy.forReply] constructor is used to create a proxy for |
| 130 * the object that will be the reply to a message send. |
| 131 */ |
| 132 ProxyImpl.forReply(Promise<SendPort> port) |
| 133 : super.forReply(port) { } |
| 134 |
| 135 } |
| 136 |
| 137 |
| 138 class Dispatcher<T> { |
| 139 |
| 140 Dispatcher(this.target) { } |
| 141 |
| 142 void _serve(ReceivePort port) { |
| 143 port.receive((var message, SendPort replyTo) { |
| 144 this.process(message, void reply(var response) { |
| 145 Proxy proxy = new Proxy.forPort(replyTo); |
| 146 proxy.send([response]); |
| 147 }); |
| 148 }); |
| 149 } |
| 150 |
| 151 static SendPort serve(Dispatcher dispatcher) { |
| 152 ReceivePort port = ProxyBase.register(dispatcher); |
| 153 dispatcher._serve(port); |
| 154 return port.toSendPort(); |
| 155 } |
| 156 |
| 157 // BUG(5015671): DartC doesn't support 'abstract' yet. |
| 158 /* abstract */ void process(var message, void reply(var response)) { |
| 159 throw "Abstract method called"; |
| 160 } |
| 161 |
| 162 T target; |
| 163 |
| 164 } |
| 165 |
| 166 // When a promise is sent across a port, it is converted to a |
| 167 // Promise<SendPort> down which we must send a port to receive the |
| 168 // completion value. Hand the Promise<SendPort> to this class to deal |
| 169 // with it. |
| 170 |
| 171 class PromiseProxy<T> extends PromiseImpl<T> { |
| 172 PromiseProxy(Promise<SendPort> sendCompleter) { |
| 173 ReceivePort completer = new ReceivePort.singleShot(); |
| 174 completer.receive((var msg, SendPort _) { |
| 175 complete(msg[0]); |
| 176 }); |
| 177 sendCompleter.addCompleteHandler((SendPort port) { |
| 178 port.send([completer.toSendPort()], null); |
| 179 }); |
| 180 } |
| 181 } |
| 6 | 182 |
| 7 class PromiseImpl<T> implements Promise<T> { | 183 class PromiseImpl<T> implements Promise<T> { |
| 8 | 184 |
| 9 // Enumeration of possible states: | 185 // Enumeration of possible states: |
| 10 static final int CREATED = 0; | 186 static final int CREATED = 0; |
| 11 static final int RUNNING = 1; | 187 static final int RUNNING = 1; |
| 12 static final int COMPLETE_NORMAL = 2; | 188 static final int COMPLETE_NORMAL = 2; |
| 13 static final int COMPLETE_ERROR = 3; | 189 static final int COMPLETE_ERROR = 3; |
| 14 static final int CANCELLED = 4; | 190 static final int CANCELLED = 4; |
| 15 | 191 |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 } | 546 } |
| 371 } | 547 } |
| 372 return process(marshalled); | 548 return process(marshalled); |
| 373 }).flatten(); | 549 }).flatten(); |
| 374 } | 550 } |
| 375 | 551 |
| 376 Promise<SendPort> _promise; | 552 Promise<SendPort> _promise; |
| 377 static Map<SendPort, Dispatcher> _dispatchers; | 553 static Map<SendPort, Dispatcher> _dispatchers; |
| 378 | 554 |
| 379 } | 555 } |
| OLD | NEW |