Last active
August 29, 2015 14:25
-
-
Save pstjvn/f0197e09381eb346160b to your computer and use it in GitHub Desktop.
2 phase RAF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(global) { | |
var tasks = [[], []]; | |
var doubleBufferIndex = 0; | |
var requestFrame = false; | |
var taskId = 0; | |
var running = false; | |
function requestAnimationFrame_() { | |
if (requestFrame) return; | |
requestFrame = true; | |
global.requestAnimationFrame(runTasks); | |
} | |
/// The actual function that will be called on each raf. | |
/// @param {!number} hrts The high-resolution timestamp from RAF | |
function runTasks(hrts) { | |
running = true; | |
requestFrame = false; | |
var taskArray = tasks[doubleBufferIndex]; | |
var taskLength = taskArray.length; | |
// During the runTask call, if there are recursive call to queue up more takas for the | |
// next frame double buffering is used to avoid scheduling in the same list | |
// and potentially run the task twice in a single run. | |
doubleBufferIndex = (doubleBufferIndex + 1) % 2; | |
var task; | |
// Run the measure phase | |
for (var i = 0; i < taskLength; i++) { | |
task = taskArray[i]; | |
task.isScheduled = false; | |
// Check if defined, specs might define only one of the two tasks. | |
if (task.measureTask) { | |
task.measureTask.call(task.context, hrts, task.state); | |
} | |
} | |
// Run the mutate phase | |
for (var i = 0; i < taskLength; i++) { | |
task = taskArray[i]; | |
task.isScheduled = false; | |
if (task.mutateTask) { | |
task.mutateTask.call(task.context, hrts, task.state); | |
} | |
} | |
// Avoid re-creating the array, instead tell the engine to consider the | |
// allready allocated memory as zeor length list. This will keep the allocation | |
// and will only allocate more mem if you ever put more items in it. | |
taskArray.length = 0; | |
running = false; | |
} | |
/// Actual exported method. | |
/// @param {{measure: function(!number, !Object), mutate: function(!number, !Object)}} specs | |
/// @param {Object=} context | |
global.createTask = function(specs, context) { | |
var id = taskId++; | |
var taskSet = { | |
id: id, | |
measureTask: specs.measure, | |
mutateTask: specs.mutate, | |
context: context | |
state: {}, | |
isScheduled: false | |
}; | |
// Return a function that can be called whenever event triggers the raf. | |
return function() { | |
if (!context) { | |
taskSet.context = this; | |
} | |
if (!taskSet.isScheduled) { | |
taskSet.isScheduled = true; | |
var taskArray = tasks[doubleBufferIndex]; | |
taskArray.push(taskSet); | |
} | |
requestAnimationFrame_(); | |
} | |
} | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment