Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / src / tracing / importer / task.js
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.require('tvcm.raf');
8 tvcm.require('tvcm.promise');
9
10 tvcm.exportTo('tracing.importer', function() {
11   /**
12    * A task is a combination of a run callback, a set of subtasks, and an after
13    * task.
14    *
15    * When executed, a task does the following things:
16    * 1. Runs its callback
17    * 2. Runs its subtasks
18    * 3. Runs its after callback.
19    *
20    * The list of subtasks and after task can be mutated inside step #1 but as
21    * soon as the task's callback returns, the subtask list and after task is
22    * fixed and cannot be changed again.
23    *
24    * Use task.after().after().after() to describe the toplevel passes that make
25    * up your computation. Then, use subTasks to add detail to each subtask as it
26    * runs. For example:
27    *    var pieces = [];
28    *    taskA = new Task(function() { pieces = getPieces(); });
29    *    taskA.after(function(taskA) {
30    *      pieces.forEach(function(piece) {
31    *        taskA.subTask(function(taskB) { piece.process(); }, this);
32    *      });
33    *    });
34    *
35    * @constructor
36    */
37   function Task(runCb, thisArg) {
38     if (thisArg === undefined)
39       throw new Error('Almost certainly, you meant to pass a thisArg.');
40     this.runCb_ = runCb;
41     this.thisArg_ = thisArg;
42     this.afterTask_ = undefined;
43     this.subTasks_ = [];
44   }
45
46   Task.prototype = {
47     /*
48      * See constructor documentation on semantics of subtasks.
49      */
50     subTask: function(cb, thisArg) {
51       if (cb instanceof Task)
52         this.subTasks_.push(cb);
53       else
54         this.subTasks_.push(new Task(cb, thisArg));
55       return this.subTasks_[this.subTasks_.length - 1];
56     },
57
58     /**
59      * Runs the current task and returns the task that should be executed next.
60      */
61     run: function() {
62       this.runCb_.call(this.thisArg_, this);
63       var subTasks = this.subTasks_;
64       this.subTasks_ = undefined; // Prevent more subTasks from being posted.
65
66       if (!subTasks.length)
67         return this.afterTask_;
68
69       // If there are subtasks, then we want to execute all the subtasks and
70       // then this task's afterTask. To make this happen, we update the
71       // afterTask of all the subtasks so the point upward to each other, e.g.
72       // subTask[0].afterTask to subTask[1] and so on. Then, the last subTask's
73       // afterTask points at this task's afterTask.
74       for (var i = 1; i < subTasks.length; i++)
75         subTasks[i - 1].afterTask_ = subTasks[i];
76       subTasks[subTasks.length - 1].afterTask_ = this.afterTask_;
77       return subTasks[0];
78     },
79
80     /*
81      * See constructor documentation on semantics of after tasks.
82      */
83     after: function(cb, thisArg) {
84       if (this.afterTask_)
85         throw new Error('Has an after task already');
86       if (cb instanceof Task)
87         this.afterTask_ = cb;
88       else
89         this.afterTask_ = new Task(cb, thisArg);
90       return this.afterTask_;
91     }
92   };
93
94   Task.RunSynchronously = function(task) {
95     var curTask = task;
96     while (curTask)
97       curTask = curTask.run();
98   }
99
100   /**
101    * Runs a task using raf.requestIdleCallback, returning
102    * a promise for its completion.
103    */
104   Task.RunWhenIdle = function(task) {
105     return new tvcm.Promise(function(resolver) {
106       var curTask = task;
107       function runAnother() {
108         try {
109           curTask = curTask.run();
110         } catch (e) {
111           resolver.reject(e);
112           console.log(e);
113           return;
114         }
115
116         if (curTask) {
117           tvcm.requestIdleCallback(runAnother);
118           return;
119         }
120
121         resolver.resolve();
122       }
123       tvcm.requestIdleCallback(runAnother);
124     });
125   }
126
127   return {
128     Task: Task
129   };
130 });