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

Unified Diff: client/html/src/Measurement.dart

Issue 8363040: Implement measurement using futures (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to all comments Created 9 years, 2 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
Index: client/html/src/Measurement.dart
diff --git a/client/html/src/Measurement.dart b/client/html/src/Measurement.dart
new file mode 100644
index 0000000000000000000000000000000000000000..102f668026e591ffd0400e5a64688a7f3dbb0b02
--- /dev/null
+++ b/client/html/src/Measurement.dart
@@ -0,0 +1,100 @@
+// 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.
+
+typedef Object ComputeValue();
+
+class MeasurementRequest<T> {
+ final ComputeValue computeValue;
+ final Completer<T> completer;
+ Object value;
+ bool exception = false;
+ MeasurementRequest(this.computeValue, this.completer);
+}
+
+final _MEASUREMENT_MESSAGE = "DART-MEASURE";
+List<MeasurementRequest> _pendingRequests;
+List<TimeoutHandler> _pendingMeasurementFrameCallbacks;
+bool _nextMeasurementFrameScheduled = false;
+bool _firstMeasurementRequest = true;
+
+void _maybeScheduleMeasurementFrame() {
+ if (!_nextMeasurementFrameScheduled) {
nweiz 2011/10/28 03:58:38 Style nit: if (_nextMeasurementFrameScheduled) ret
Jacob 2011/10/31 22:09:50 Done.
+ _nextMeasurementFrameScheduled = true;
+ // postMessage gives us a way to receive a callback after the current
+ // event listener has unwound but before the browser has repainted.
+ if (_firstMeasurementRequest) {
+ // Messages from other windows do not cause a security risk as
+ // all we care about is that _onCompleteMeasurementRequests is called
+ // after the current event loop is unwound and calling the function is
+ // a noop if no requests are pending.
nweiz 2011/10/28 03:58:38 How sure are we that it isn't possible to at least
Jacob 2011/10/31 22:09:50 100% sure due to the early terminate at the start
+ window.on.message.add(Isolate.bind(
nweiz 2011/10/28 03:58:38 I believe Isolate.bind is no longer necessary (see
Jacob 2011/10/31 22:09:50 Done.
+ (e) => _onCompleteMeasurementFutures()
nweiz 2011/10/28 03:58:38 Style nit: 4 spaces
Jacob 2011/10/31 22:09:50 Done.
+ ));
+ _firstMeasurementRequest = false;
+ }
+
+ // TODO(jacobr): other mechanisms such as setImmediate and
+ // requestAnimationFrame may work better of platforms that support them.
+ // The key is we need a way to execute code immediately after the current
+ // event listener queue unwinds.
+ window.postMessage(_MEASUREMENT_MESSAGE, "*");
+ }
+}
+
+void _addMeasurementFrameCallback(TimeoutHandler callback) {
nweiz 2011/10/28 03:58:38 It would be nice to have some documentation for th
Jacob 2011/10/31 22:09:50 Agreed. Added some flower box comments
+ if (null == _pendingMeasurementFrameCallbacks) {
+ _pendingMeasurementFrameCallbacks = <TimeoutHandler>[];
+ _maybeScheduleMeasurementFrame();
+ }
+ _pendingMeasurementFrameCallbacks.add(callback);
+}
+
+Future _createMeasurementFuture(ComputeValue computeValue,
+ Completer completer) {
+ if (null == _pendingRequests) {
+ _pendingRequests = <MeasurementRequest>[];
+ _maybeScheduleMeasurementFrame();
+ }
+ _pendingRequests.add(new MeasurementRequest(computeValue, completer));
+ return completer.future;
+}
+
+void _onCompleteMeasurementFutures() {
nweiz 2011/10/28 03:58:38 I feel like this name suggests that the function i
Jacob 2011/10/31 22:09:50 Done.
+ if (_nextMeasurementFrameScheduled == false) {
+ // Ignore spurious call to this function.
+ return;
+ }
+
+ _nextMeasurementFrameScheduled = false;
+ // We must compute all new values before fulfilling the futures as
+ // the onComplete callbacks for the futures could modify the DOM making
+ // subsequent measurement calculations expensive to compute.
+ for (MeasurementRequest request in _pendingRequests) {
+ try {
+ request.value = request.computeValue();
+ } catch(var e) {
+ request.value = e;
+ request.exception = true;
+ }
+ }
+
+ final completedRequests = _pendingRequests;
+ final readyMeasurementFrameCallbacks = _pendingMeasurementFrameCallbacks;
+ _pendingRequests = null;
+ _pendingMeasurementFrameCallbacks = null;
+ for (MeasurementRequest request in completedRequests) {
+ if (request.exception) {
+ request.completer.completeException(request.value);
+ } else {
+ request.completer.complete(request.value);
+ }
+ }
+
+ if (null != readyMeasurementFrameCallbacks) {
+ for (TimeoutHandler handler in readyMeasurementFrameCallbacks) {
+ // TODO(jacobr): wrap each call to a handler in a try-catch block.
+ handler();
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698