Skip to content

Commit

Permalink
[scheduler] Deadline object -> shouldYield (facebook#14025)
Browse files Browse the repository at this point in the history
* [scheduler] Deadline object -> shouldYield

Instead of using a requestIdleCallback-style deadline object, expose a
method Scheduler.shouldYield that returns true if there's a higher
priority event in the queue.

* Nits
  • Loading branch information
acdlite authored and jetoneza committed Jan 23, 2019
1 parent 25f98a5 commit c1827bc
Show file tree
Hide file tree
Showing 18 changed files with 215 additions and 249 deletions.
1 change: 1 addition & 0 deletions packages/react-art/src/ReactARTHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
export {
unstable_now as now,
unstable_scheduleCallback as scheduleDeferredCallback,
unstable_shouldYield as shouldYield,
unstable_cancelCallback as cancelDeferredCallback,
} from 'scheduler';
import Transform from 'art/core/transform';
Expand Down
1 change: 1 addition & 0 deletions packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type NoTimeout = -1;
export {
unstable_now as now,
unstable_scheduleCallback as scheduleDeferredCallback,
unstable_shouldYield as shouldYield,
unstable_cancelCallback as cancelDeferredCallback,
} from 'scheduler';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ export const scheduleDeferredCallback =
ReactNativeFrameScheduling.scheduleDeferredCallback;
export const cancelDeferredCallback =
ReactNativeFrameScheduling.cancelDeferredCallback;
export const shouldYield = ReactNativeFrameScheduling.shouldYield;

export const scheduleTimeout = setTimeout;
export const cancelTimeout = clearTimeout;
Expand Down
21 changes: 8 additions & 13 deletions packages/react-native-renderer/src/ReactNativeFrameScheduling.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,16 @@
* @flow
*/

import type {Deadline} from 'react-reconciler/src/ReactFiberScheduler';

const hasNativePerformanceNow =
typeof performance === 'object' && typeof performance.now === 'function';

const now = hasNativePerformanceNow
? () => performance.now()
: () => Date.now();

type Callback = (deadline: Deadline) => void;

let scheduledCallback: Callback | null = null;
let scheduledCallback: (() => mixed) | null = null;
let frameDeadline: number = 0;

const frameDeadlineObject: Deadline = {
timeRemaining: () => frameDeadline - now(),
didTimeout: false,
};

function setTimeoutCallback() {
// TODO (bvaughn) Hard-coded 5ms unblocks initial async testing.
// React API probably changing to boolean rather than time remaining.
Expand All @@ -36,15 +27,15 @@ function setTimeoutCallback() {
const callback = scheduledCallback;
scheduledCallback = null;
if (callback !== null) {
callback(frameDeadlineObject);
callback();
}
}

// RN has a poor polyfill for requestIdleCallback so we aren't using it.
// This implementation is only intended for short-term use anyway.
// We also don't implement cancel functionality b'c Fiber doesn't currently need it.
function scheduleDeferredCallback(
callback: Callback,
callback: () => mixed,
options?: {timeout: number},
): number {
// We assume only one callback is scheduled at a time b'c that's how Fiber works.
Expand All @@ -58,4 +49,8 @@ function cancelDeferredCallback(callbackID: number) {
clearTimeout((callbackID: any)); // Timeouts are always numbers on RN
}

export {now, scheduleDeferredCallback, cancelDeferredCallback};
function shouldYield() {
return frameDeadline <= now();
}

export {now, scheduleDeferredCallback, cancelDeferredCallback, shouldYield};
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ export const scheduleDeferredCallback =
ReactNativeFrameScheduling.scheduleDeferredCallback;
export const cancelDeferredCallback =
ReactNativeFrameScheduling.cancelDeferredCallback;
export const shouldYield = ReactNativeFrameScheduling.shouldYield;

export const scheduleTimeout = setTimeout;
export const cancelTimeout = clearTimeout;
Expand Down
63 changes: 37 additions & 26 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
scheduledCallbackTimeout === -1 ||
scheduledCallbackTimeout > newTimeout
) {
scheduledCallbackTimeout = newTimeout;
scheduledCallbackTimeout = elapsedTimeInMs + newTimeout;
}
}
return 0;
Expand All @@ -333,6 +333,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
scheduledCallbackTimeout = -1;
},

shouldYield,

scheduleTimeout: setTimeout,
cancelTimeout: clearTimeout,
noTimeout: -1,
Expand Down Expand Up @@ -512,35 +514,44 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

let yieldedValues = null;

let didYield;
let unitsRemaining;

function* flushUnitsOfWork(n: number): Generator<Array<mixed>, void, void> {
let didStop = false;
while (!didStop && scheduledCallback !== null) {
let cb = scheduledCallback;
scheduledCallback = null;
unitsRemaining = n;
cb({
timeRemaining() {
if (yieldedValues !== null) {
return 0;
}
if (unitsRemaining-- > 0) {
return 999;
}
didStop = true;
return 0;
},
didTimeout:
scheduledCallbackTimeout !== -1 &&
elapsedTimeInMs > scheduledCallbackTimeout,
});
function shouldYield() {
if (
scheduledCallbackTimeout === -1 ||
elapsedTimeInMs > scheduledCallbackTimeout
) {
return false;
} else {
if (didYield || yieldedValues !== null) {
return true;
}
if (unitsRemaining-- > 0) {
return false;
}
didYield = true;
return true;
}
}

if (yieldedValues !== null) {
const values = yieldedValues;
yieldedValues = null;
yield values;
function* flushUnitsOfWork(n: number): Generator<Array<mixed>, void, void> {
unitsRemaining = n + 1;
didYield = false;
try {
while (!didYield && scheduledCallback !== null) {
let cb = scheduledCallback;
scheduledCallback = null;
cb();
if (yieldedValues !== null) {
const values = yieldedValues;
yieldedValues = null;
yield values;
}
}
} finally {
unitsRemaining = -1;
didYield = false;
}
}

Expand Down
Loading

0 comments on commit c1827bc

Please sign in to comment.