| Index: sky/specs/runloop.md
|
| diff --git a/sky/specs/runloop.md b/sky/specs/runloop.md
|
| deleted file mode 100644
|
| index b080090af1b1d6b4e2fe487d21d4fd569b36bbe2..0000000000000000000000000000000000000000
|
| --- a/sky/specs/runloop.md
|
| +++ /dev/null
|
| @@ -1,144 +0,0 @@
|
| -Sky's Run Loop
|
| -==============
|
| -
|
| -Sky has three task queues, named idle, frame, and nextFrame.
|
| -
|
| -When a task is run, it has a time budget, and if the time budget is
|
| -exceeded, then a catchable DeadlineExceededException exception is
|
| -fired.
|
| -
|
| -```dart
|
| -class DeadlineExceededException implements Exception { }
|
| -```
|
| -
|
| -There is a method you can use that guards your code against these
|
| -exceptions:
|
| -
|
| -```dart
|
| -typedef void Callback();
|
| -external guardAgainstDeadlineExceptions(Callback callback);
|
| -// runs callback.
|
| -// if the time budget for the _task_ expires while the callback is
|
| -// running, the callback isn't interrupted, but the method will throw
|
| -// an exception once the callback returns.
|
| -```
|
| -
|
| -When Sky is to *process a task queue until a particular time*, with a
|
| -queue *relevant task queue*, bits *filter bits*, a time
|
| -*particular time*, and an *idle rule* which is either "sleep" or
|
| -"abort", it must run the following steps:
|
| -
|
| -1. Let *remaining time* be the time until the given *particular time*.
|
| -2. If *remaining time* is less than or equal to zero, exit this
|
| - algorithm.
|
| -3. Let *task list* be the list of tasks in the *relevant task queue*
|
| - that have bits that, when 'and'ed with *filter bits*, are equal to
|
| - *filter bits*, whose required budget is less than or equal to
|
| - *remaining time*; and whose due time, if any, has been reached.
|
| -4. If *task list* is empty, then if *idle rule* is "sleep" then return
|
| - to step 1, otherwise, exit this algorithm.
|
| -5. Sort *task list* by the priority of each task, highest first.
|
| -6. Remove the top task from *task list* from the *relevant task
|
| - queue*, and let that be *selected task*.
|
| -7. Run *selected task*, with a budget of *remaining time* or 1ms,
|
| - whichever is shorter.
|
| -8. Return to step 1.
|
| -
|
| -When Sky is to *drain a task queue for a specified time*, with a queue
|
| -*relevant task queue*, bits *filter bits*, and a duration *budget*, it
|
| -must run the following steps:
|
| -
|
| -2. Let *task list* be the list of tasks in the *relevant task queue*
|
| - that have bits that, when 'or'ed with *filter bits*, are non-zero;
|
| - and whose required budget is less than or equal to *budget*.
|
| -4. If *task list* is empty, then exit.
|
| -5. Sort *task list* by the priority of each task, highest first.
|
| -6. Remove the top task from *task list* from the *relevant task
|
| - queue*, and let that be *selected task*.
|
| -7. Run *selected task*, with a budget of *budget*.
|
| -8. Decrease *budget* with the amount of time that *selected task* took
|
| - to run.
|
| -9. If *selected task* threw an uncaught DeadlineExceededException
|
| - exception, then cancel all the tasks in *relevant task queue*.
|
| - Otherwise, return to step 2.
|
| -
|
| -Sky's run loop consists of running the following, at 120Hz (each loop
|
| -takes 8.333ms):
|
| -
|
| -1. *Drain* the *frame task queue*, with bits
|
| - `application.frameTaskBits`, for 1ms.
|
| -
|
| -2. Create a task that does the following, then run it with a budget of
|
| - 1ms:
|
| -
|
| - 1. Update the render tree, including calling childAdded(),
|
| - childRemoved(), and getLayoutManager() as needed, catching any
|
| - exceptions other than DeadlineExceededException exceptions.
|
| -
|
| - If an exception is thrown by this, then the RenderNode tree will
|
| - continue to not quite match the element tree, which is fine.
|
| -
|
| -3. If there are no tasks on the *idle task queue* with bits
|
| - `LayoutKind`, create a task that tells the root node to layout if
|
| - it has needsLayout or descendantNeedsLayout, mark that with
|
| - priority 0 and bits `LayoutKind`, and add it to the *idle task
|
| - queue*.
|
| -
|
| -4. *Process* the *idle task queue*, with bits `LayoutKind`, with a
|
| - target time of t-1ms, where t is the time at which we have to send
|
| - the frame to the GPU, and with an *idle rule* of "abort".
|
| -
|
| -5. Create a task that does the following, then run it with a budget of
|
| - 1ms:
|
| -
|
| - 1. If there are no RenderNodes that need paint, abort.
|
| -
|
| - 2. Call the `paint()` callback of the RenderNode that was least
|
| - recently marked as needing paint, catching any exceptions other
|
| - than DeadlineExceededException exceptions.
|
| -
|
| - 3. Jump to step 1.
|
| -
|
| - If an exception is thrown by this, then some RenderNode objects
|
| - will be out-of-date during the paint.
|
| -
|
| -6. Send frame to GPU.
|
| -
|
| -7. Replace the frame queue with the nextFrame queue, and let the
|
| - nextFrame queue be an empty queue.
|
| -
|
| -8. *Process* the *idle task queue*, with bits
|
| - `application.idleTaskBits`, with a target time of t, where t is the
|
| - time at which we have to start the next frame's layout and paint
|
| - computations, and with an *idle rule* of "sleep".
|
| -
|
| -TODO(ianh): Update the timings above to have some relationship to
|
| -reality.
|
| -
|
| -TODO(ianh): Define an API so that the application can adjust the
|
| -budgets.
|
| -
|
| -Task kinds and priorities
|
| --------------------------
|
| -
|
| -Tasks scheduled by futures get the priority and task kind bits from
|
| -the task they are scheduled from.
|
| -
|
| -```dart
|
| -int IdlePriority = 0; // tasks that can be delayed arbitrarily
|
| -int FutureLayoutPriority = 1000; // async-layout tasks
|
| -int AnimationPriority = 3000; // animation-related tasks
|
| -int InputPriority = 4000; // input events
|
| -int ScrollPriority = 5000; // framework-fired events for scrolling
|
| -
|
| -// possible idle queue task bits
|
| -int IdleKind = 0x01; // tasks that should run during the idle loop
|
| -int LayoutKind = 0x02; // tasks that should run during layout
|
| -int TouchSafeKind = 0x04; // tasks that should keep running while there is a pointer down
|
| -int idleTaskBits = IdleKind; // tasks must have all these bits to run during idle loop
|
| -int layoutTaskBits = LayoutKind; // tasks must have all these bits to run during layout
|
| -
|
| -// possible frame queue task bits
|
| -// (there are none at this time)
|
| -int frameTaskBits = 0x00; // tasks must have all these bits to run during the frame loop
|
| -```
|
|
|