UNPKG

10.7 kBJavaScriptView Raw
1// Copyright (c) Microsoft, All rights reserved. See License.txt in the project root for license information.
2
3;(function (factory) {
4 var objectTypes = {
5 'function': true,
6 'object': true
7 };
8
9 function checkGlobal(value) {
10 return (value && value.Object === Object) ? value : null;
11 }
12
13 var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
14 var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
15 var freeGlobal = checkGlobal(freeExports && freeModule && typeof global === 'object' && global);
16 var freeSelf = checkGlobal(objectTypes[typeof self] && self);
17 var freeWindow = checkGlobal(objectTypes[typeof window] && window);
18 var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null;
19 var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
20 var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
21
22 // Because of build optimizers
23 if (typeof define === 'function' && define.amd) {
24 define(['./rx'], function (Rx, exports) {
25 return factory(root, exports, Rx);
26 });
27 } else if (typeof module === 'object' && module && module.exports === freeExports) {
28 module.exports = factory(root, module.exports, require('./rx'));
29 } else {
30 root.Rx = factory(root, {}, root.Rx);
31 }
32}.call(this, function (root, exp, Rx, undefined) {
33
34 // Aliases
35 var Scheduler = Rx.Scheduler,
36 ScheduledItem = Rx.internals.ScheduledItem,
37 SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive,
38 PriorityQueue = Rx.internals.PriorityQueue,
39 inherits = Rx.internals.inherits,
40 defaultSubComparer = Rx.helpers.defaultSubComparer,
41 notImplemented = Rx.helpers.notImplemented;
42
43 /** Provides a set of extension methods for virtual time scheduling. */
44 var VirtualTimeScheduler = Rx.VirtualTimeScheduler = (function (__super__) {
45 inherits(VirtualTimeScheduler, __super__);
46
47 /**
48 * Creates a new virtual time scheduler with the specified initial clock value and absolute time comparer.
49 *
50 * @constructor
51 * @param {Number} initialClock Initial value for the clock.
52 * @param {Function} comparer Comparer to determine causality of events based on absolute time.
53 */
54 function VirtualTimeScheduler(initialClock, comparer) {
55 this.clock = initialClock;
56 this.comparer = comparer;
57 this.isEnabled = false;
58 this.queue = new PriorityQueue(1024);
59 __super__.call(this);
60 }
61
62 var VirtualTimeSchedulerPrototype = VirtualTimeScheduler.prototype;
63
64 VirtualTimeSchedulerPrototype.now = function () {
65 return this.toAbsoluteTime(this.clock);
66 };
67
68 VirtualTimeSchedulerPrototype.schedule = function (state, action) {
69 return this.scheduleAbsolute(state, this.clock, action);
70 };
71
72 VirtualTimeSchedulerPrototype.scheduleFuture = function (state, dueTime, action) {
73 var dt = dueTime instanceof Date ?
74 this.toRelativeTime(dueTime - this.now()) :
75 this.toRelativeTime(dueTime);
76
77 return this.scheduleRelative(state, dt, action);
78 };
79
80 /**
81 * Adds a relative time value to an absolute time value.
82 * @param {Number} absolute Absolute virtual time value.
83 * @param {Number} relative Relative virtual time value to add.
84 * @return {Number} Resulting absolute virtual time sum value.
85 */
86 VirtualTimeSchedulerPrototype.add = notImplemented;
87
88 /**
89 * Converts an absolute time to a number
90 * @param {Any} The absolute time.
91 * @returns {Number} The absolute time in ms
92 */
93 VirtualTimeSchedulerPrototype.toAbsoluteTime = notImplemented;
94
95 /**
96 * Converts the TimeSpan value to a relative virtual time value.
97 * @param {Number} timeSpan TimeSpan value to convert.
98 * @return {Number} Corresponding relative virtual time value.
99 */
100 VirtualTimeSchedulerPrototype.toRelativeTime = notImplemented;
101
102 /**
103 * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be emulated using recursive scheduling.
104 * @param {Mixed} state Initial state passed to the action upon the first iteration.
105 * @param {Number} period Period for running the work periodically.
106 * @param {Function} action Action to be executed, potentially updating the state.
107 * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
108 */
109 VirtualTimeSchedulerPrototype.schedulePeriodic = function (state, period, action) {
110 var s = new SchedulePeriodicRecursive(this, state, period, action);
111 return s.start();
112 };
113
114 /**
115 * Schedules an action to be executed after dueTime.
116 * @param {Mixed} state State passed to the action to be executed.
117 * @param {Number} dueTime Relative time after which to execute the action.
118 * @param {Function} action Action to be executed.
119 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
120 */
121 VirtualTimeSchedulerPrototype.scheduleRelative = function (state, dueTime, action) {
122 var runAt = this.add(this.clock, dueTime);
123 return this.scheduleAbsolute(state, runAt, action);
124 };
125
126 /**
127 * Starts the virtual time scheduler.
128 */
129 VirtualTimeSchedulerPrototype.start = function () {
130 if (!this.isEnabled) {
131 this.isEnabled = true;
132 do {
133 var next = this.getNext();
134 if (next !== null) {
135 this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
136 next.invoke();
137 } else {
138 this.isEnabled = false;
139 }
140 } while (this.isEnabled);
141 }
142 };
143
144 /**
145 * Stops the virtual time scheduler.
146 */
147 VirtualTimeSchedulerPrototype.stop = function () {
148 this.isEnabled = false;
149 };
150
151 /**
152 * Advances the scheduler's clock to the specified time, running all work till that point.
153 * @param {Number} time Absolute time to advance the scheduler's clock to.
154 */
155 VirtualTimeSchedulerPrototype.advanceTo = function (time) {
156 var dueToClock = this.comparer(this.clock, time);
157 if (this.comparer(this.clock, time) > 0) { throw new ArgumentOutOfRangeError(); }
158 if (dueToClock === 0) { return; }
159 if (!this.isEnabled) {
160 this.isEnabled = true;
161 do {
162 var next = this.getNext();
163 if (next !== null && this.comparer(next.dueTime, time) <= 0) {
164 this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
165 next.invoke();
166 } else {
167 this.isEnabled = false;
168 }
169 } while (this.isEnabled);
170 this.clock = time;
171 }
172 };
173
174 /**
175 * Advances the scheduler's clock by the specified relative time, running all work scheduled for that timespan.
176 * @param {Number} time Relative time to advance the scheduler's clock by.
177 */
178 VirtualTimeSchedulerPrototype.advanceBy = function (time) {
179 var dt = this.add(this.clock, time),
180 dueToClock = this.comparer(this.clock, dt);
181 if (dueToClock > 0) { throw new ArgumentOutOfRangeError(); }
182 if (dueToClock === 0) { return; }
183
184 this.advanceTo(dt);
185 };
186
187 /**
188 * Advances the scheduler's clock by the specified relative time.
189 * @param {Number} time Relative time to advance the scheduler's clock by.
190 */
191 VirtualTimeSchedulerPrototype.sleep = function (time) {
192 var dt = this.add(this.clock, time);
193 if (this.comparer(this.clock, dt) >= 0) { throw new ArgumentOutOfRangeError(); }
194
195 this.clock = dt;
196 };
197
198 /**
199 * Gets the next scheduled item to be executed.
200 * @returns {ScheduledItem} The next scheduled item.
201 */
202 VirtualTimeSchedulerPrototype.getNext = function () {
203 while (this.queue.length > 0) {
204 var next = this.queue.peek();
205 if (next.isCancelled()) {
206 this.queue.dequeue();
207 } else {
208 return next;
209 }
210 }
211 return null;
212 };
213
214 /**
215 * Schedules an action to be executed at dueTime.
216 * @param {Mixed} state State passed to the action to be executed.
217 * @param {Number} dueTime Absolute time at which to execute the action.
218 * @param {Function} action Action to be executed.
219 * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
220 */
221 VirtualTimeSchedulerPrototype.scheduleAbsolute = function (state, dueTime, action) {
222 var self = this;
223
224 function run(scheduler, state1) {
225 self.queue.remove(si);
226 return action(scheduler, state1);
227 }
228
229 var si = new ScheduledItem(this, state, run, dueTime, this.comparer);
230 this.queue.enqueue(si);
231
232 return si.disposable;
233 };
234
235 return VirtualTimeScheduler;
236 }(Scheduler));
237
238 /** Provides a virtual time scheduler that uses Date for absolute time and number for relative time. */
239 Rx.HistoricalScheduler = (function (__super__) {
240 inherits(HistoricalScheduler, __super__);
241
242 /**
243 * Creates a new historical scheduler with the specified initial clock value.
244 * @constructor
245 * @param {Number} initialClock Initial value for the clock.
246 * @param {Function} comparer Comparer to determine causality of events based on absolute time.
247 */
248 function HistoricalScheduler(initialClock, comparer) {
249 var clock = initialClock == null ? 0 : initialClock;
250 var cmp = comparer || defaultSubComparer;
251 __super__.call(this, clock, cmp);
252 }
253
254 var HistoricalSchedulerProto = HistoricalScheduler.prototype;
255
256 /**
257 * Adds a relative time value to an absolute time value.
258 * @param {Number} absolute Absolute virtual time value.
259 * @param {Number} relative Relative virtual time value to add.
260 * @return {Number} Resulting absolute virtual time sum value.
261 */
262 HistoricalSchedulerProto.add = function (absolute, relative) {
263 return absolute + relative;
264 };
265
266 HistoricalSchedulerProto.toAbsoluteTime = function (absolute) {
267 return new Date(absolute).getTime();
268 };
269
270 /**
271 * Converts the TimeSpan value to a relative virtual time value.
272 * @memberOf HistoricalScheduler
273 * @param {Number} timeSpan TimeSpan value to convert.
274 * @return {Number} Corresponding relative virtual time value.
275 */
276 HistoricalSchedulerProto.toRelativeTime = function (timeSpan) {
277 return timeSpan;
278 };
279
280 return HistoricalScheduler;
281 }(Rx.VirtualTimeScheduler));
282
283 return Rx;
284}));