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

Side by Side Diff: quiver/lib/src/async/metronome.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 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 unified diff | Download patch
« no previous file with comments | « quiver/lib/src/async/iteration.dart ('k') | quiver/lib/src/async/stream_router.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 part of quiver.async;
16
17 /**
18 * A stream of [DateTime] events at [interval]s centered on [anchor].
19 *
20 * This stream accounts for drift but only guarantees that events are
21 * delivered on or after the interval. If the system is busy for longer than
22 * two [interval]s, only one will be delivered.
23 *
24 * [anchor] defaults to [clock.now], which means the stream represents a
25 * self-correcting periodic timer. If anchor is the epoch, then the stream is
26 * synchronized to wall-clock time. It can be anchored anywhere in time, but
27 * this does not delay the first delivery.
28 *
29 * Examples:
30 *
31 * new Metronome.epoch(aMinute).listen((d) => print(d));
32 *
33 * Could print the following stream of events, anchored by epoch,
34 * till the stream is canceled:
35 * 2014-05-04 14:06:00.001
36 * 2014-05-04 14:07:00.000
37 * 2014-05-04 14:08:00.003
38 * ...
39 *
40 * Example anchored in the future (now = 2014-05-05 20:06:00.123)
41 * new IsochronousStream.periodic(aMillisecond * 100,
42 * anchorMs: DateTime.parse("2014-05-05 21:07:00"))
43 * .listen((d) => print(d));
44 *
45 * 2014-05-04 20:06:00.223
46 * 2014-05-04 20:06:00.324
47 * 2014-05-04 20:06:00.423
48 * ...
49 */
50 class Metronome extends Stream<DateTime> {
51 static final DateTime _EPOCH = new DateTime.fromMillisecondsSinceEpoch(0);
52
53 final Clock clock;
54 final Duration interval;
55 final DateTime anchor;
56
57 Timer _timer;
58 StreamController _controller;
59 final int _intervalMs;
60 final int _anchorMs;
61
62 bool get isBroadcast => true;
63
64 Metronome.epoch(Duration interval, {Clock clock: const Clock()})
65 : this._(interval, clock: clock, anchor: _EPOCH);
66
67 Metronome.periodic(Duration interval,
68 {Clock clock: const Clock(), DateTime anchor})
69 : this._(interval, clock: clock, anchor: anchor);
70
71 Metronome._(Duration interval, {Clock clock: const Clock(), DateTime anchor})
72 : this.clock = clock,
73 this.anchor = anchor,
74 this.interval = interval,
75 this._intervalMs = interval.inMilliseconds,
76 this._anchorMs = (anchor == null
77 ? clock.now()
78 : anchor).millisecondsSinceEpoch {
79 _controller = new StreamController<DateTime>.broadcast(
80 sync: true, onCancel: () {
81 _timer.cancel();
82 }, onListen: () {
83 _startTimer(clock.now());
84 });
85 }
86
87 StreamSubscription<DateTime> listen(void onData(DateTime event),
88 {Function onError, void onDone(), bool cancelOnError}) =>
89 _controller.stream.listen(onData,
90 onError: onError, onDone: onDone, cancelOnError: cancelOnError);
91
92 _startTimer(DateTime now) {
93 var delay =
94 _intervalMs - ((now.millisecondsSinceEpoch - _anchorMs) % _intervalMs);
95 _timer = new Timer(new Duration(milliseconds: delay), _tickDate);
96 }
97
98 _tickDate() {
99 // Hey now, what's all this hinky clock.now() calls? Simple, if the workers
100 // on the receiving end of _controller.add() take a non-zero amount of time
101 // to do their thing (e.g. rendering a large scene with canvas), the next
102 // timer must be adjusted to account for the lapsed time.
103 _controller.add(clock.now());
104 _startTimer(clock.now());
105 }
106 }
OLDNEW
« no previous file with comments | « quiver/lib/src/async/iteration.dart ('k') | quiver/lib/src/async/stream_router.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698