mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
74608417df
Summary: Changelog: [internal] If task that is being executed schedules a new task with higher priority, the new task will be dropped from the queue. To fix this, we always check if the top of the queue is what was executed and only then remove it. Example: Let's say there is task A with priority "normal". When we execute task A (which is not removed from the queue until later), it adds a task B with "immediate" priority. So priority queue now has two tasks: [1: B, 2: A] After task A finishes, inside workLoop, it will pop from top of the priority queue. But task A is no longer top of the priority queue (this is the bug) and it pops B. B is never executed and A is executed twice. Reviewed By: ShikaSD Differential Revision: D29841433 fbshipit-source-id: b2f1474fdfc7b3e2d42bae5b7f4ac7e6c3a37b54
104 lines
2.8 KiB
C++
104 lines
2.8 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <ReactCommon/RuntimeExecutor.h>
|
|
#include <react/renderer/runtimescheduler/RuntimeSchedulerClock.h>
|
|
#include <react/renderer/runtimescheduler/Task.h>
|
|
#include <atomic>
|
|
#include <memory>
|
|
#include <queue>
|
|
|
|
namespace facebook::react {
|
|
|
|
class RuntimeScheduler final {
|
|
public:
|
|
RuntimeScheduler(
|
|
RuntimeExecutor const &runtimeExecutor,
|
|
std::function<RuntimeSchedulerTimePoint()> now =
|
|
RuntimeSchedulerClock::now);
|
|
/*
|
|
* Not copyable.
|
|
*/
|
|
RuntimeScheduler(RuntimeScheduler const &) = delete;
|
|
RuntimeScheduler &operator=(RuntimeScheduler const &) = delete;
|
|
|
|
/*
|
|
* Not movable.
|
|
*/
|
|
RuntimeScheduler(RuntimeScheduler &&) = delete;
|
|
RuntimeScheduler &operator=(RuntimeScheduler &&) = delete;
|
|
|
|
void scheduleWork(std::function<void(jsi::Runtime &)> callback) const;
|
|
|
|
/*
|
|
* Grants access to the runtime synchronously on the caller's thread.
|
|
*
|
|
* Shouldn't be called directly. it is expected to be used
|
|
* by dispatching a synchronous event via event emitter in your native
|
|
* component.
|
|
*/
|
|
void executeNowOnTheSameThread(
|
|
std::function<void(jsi::Runtime &runtime)> callback) const;
|
|
|
|
std::shared_ptr<Task> scheduleTask(
|
|
SchedulerPriority priority,
|
|
jsi::Function callback);
|
|
|
|
void cancelTask(std::shared_ptr<Task> const &task) noexcept;
|
|
|
|
bool getShouldYield() const noexcept;
|
|
|
|
SchedulerPriority getCurrentPriorityLevel() const noexcept;
|
|
|
|
RuntimeSchedulerTimePoint now() const noexcept;
|
|
|
|
void setEnableYielding(bool enableYielding);
|
|
|
|
private:
|
|
mutable std::priority_queue<
|
|
std::shared_ptr<Task>,
|
|
std::vector<std::shared_ptr<Task>>,
|
|
TaskPriorityComparer>
|
|
taskQueue_;
|
|
|
|
RuntimeExecutor const runtimeExecutor_;
|
|
mutable SchedulerPriority currentPriority_{SchedulerPriority::NormalPriority};
|
|
mutable std::atomic_bool shouldYield_{false};
|
|
|
|
void startWorkLoop(jsi::Runtime &runtime) const;
|
|
|
|
/*
|
|
* Returns a time point representing the current point in time. May be called
|
|
* from multiple threads.
|
|
*/
|
|
std::function<RuntimeSchedulerTimePoint()> now_;
|
|
|
|
/*
|
|
* Flag indicating if callback on JavaScript queue has been
|
|
* scheduled.
|
|
*/
|
|
std::atomic_bool isCallbackScheduled_{false};
|
|
|
|
/*
|
|
* Flag indicating if yielding is enabled.
|
|
*
|
|
* If set to true and Concurrent Mode is enabled on the surface,
|
|
* React Native will ask React to yield in case any work has been scheduled.
|
|
* Default value is false
|
|
*/
|
|
bool enableYielding_{false};
|
|
|
|
/*
|
|
* This flag is set while performing work, to prevent re-entrancy.
|
|
*/
|
|
mutable bool isPerformingWork_{false};
|
|
};
|
|
|
|
} // namespace facebook::react
|