138 строки
4.1 KiB
C++
138 строки
4.1 KiB
C++
#pragma once
|
|
|
|
#include "v8.h"
|
|
#include "libplatform/libplatform.h"
|
|
#include <chrono>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <atomic>
|
|
#include <queue>
|
|
#include <condition_variable>
|
|
#include <cstdlib>
|
|
|
|
#include <jsi/V8Runtime.h>
|
|
|
|
namespace facebook {
|
|
namespace v8runtime {
|
|
|
|
class ForegroundTaskRunner : public v8::TaskRunner {
|
|
public:
|
|
|
|
ForegroundTaskRunner(std::shared_ptr<facebook::react::MessageQueueThread> queue):queue_(queue){}
|
|
|
|
void PostTask(std::unique_ptr<v8::Task> task) override;
|
|
|
|
void PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) override { std::abort(); }
|
|
|
|
void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override { std::abort(); }
|
|
|
|
bool IdleTasksEnabled() override { return false; };
|
|
private:
|
|
|
|
std::shared_ptr<facebook::react::MessageQueueThread> queue_;
|
|
};
|
|
|
|
class WorkerThreadsTaskRunner : public v8::TaskRunner {
|
|
public:
|
|
|
|
WorkerThreadsTaskRunner();
|
|
~WorkerThreadsTaskRunner();
|
|
|
|
void PostTask(std::unique_ptr<v8::Task> task) override;
|
|
|
|
void PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) override;
|
|
|
|
void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override { std::abort(); }
|
|
|
|
bool IdleTasksEnabled() override { return false; };
|
|
|
|
private:
|
|
void WorkerFunc();
|
|
void TimerFunc();
|
|
|
|
private:
|
|
|
|
using DelayedEntry = std::pair<double, std::unique_ptr<v8::Task>>;
|
|
|
|
// Define a comparison operator for the delayed_task_queue_ to make sure
|
|
// that the unique_ptr in the DelayedEntry is not accessed in the priority
|
|
// queue. This is necessary because we have to reset the unique_ptr when we
|
|
// remove a DelayedEntry from the priority queue.
|
|
struct DelayedEntryCompare {
|
|
bool operator()(DelayedEntry& left, DelayedEntry& right) {
|
|
return left.first > right.first;
|
|
}
|
|
};
|
|
|
|
std::priority_queue<DelayedEntry, std::vector<DelayedEntry>, DelayedEntryCompare> delayed_task_queue_;
|
|
std::queue<std::unique_ptr<v8::Task>> tasks_queue_;
|
|
|
|
std::mutex queue_access_mutex_;
|
|
std::condition_variable tasks_available_cond_;
|
|
|
|
std::mutex delayed_queue_access_mutex_;
|
|
std::condition_variable delayed_tasks_available_cond_;
|
|
|
|
std::atomic<bool> stop_requested_{ false };
|
|
|
|
// TODO -- This should become a semaphore when we support more than one worker thread.
|
|
std::mutex worker_stopped_mutex_;
|
|
std::condition_variable worker_stopped_cond_;
|
|
bool worker_stopped_{ false };
|
|
|
|
std::mutex timer_stopped_mutex_;
|
|
std::condition_variable timer_stopped_cond_;
|
|
bool timer_stopped_{ false };
|
|
};
|
|
|
|
constexpr int ISOLATE_DATA_SLOT = 0;
|
|
class V8Runtime;
|
|
// Platform needs to map every isolate to this data.
|
|
struct IsolateData {
|
|
IsolateData(std::shared_ptr<facebook::react::MessageQueueThread> queue, V8Runtime* runtime)
|
|
: jsQueue_(queue), runtimeimpl_(runtime) {}
|
|
std::shared_ptr<facebook::react::MessageQueueThread> jsQueue_;
|
|
V8Runtime* runtimeimpl_;
|
|
};
|
|
|
|
class V8Platform : public v8::Platform {
|
|
public:
|
|
explicit V8Platform();
|
|
~V8Platform() override;
|
|
|
|
int NumberOfWorkerThreads() override;
|
|
|
|
std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(v8::Isolate* isolate) override;
|
|
|
|
void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override;
|
|
void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, double delay_in_seconds) override;
|
|
|
|
void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override;
|
|
void CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task, double delay_in_seconds) override;
|
|
|
|
void CallIdleOnForegroundThread(v8::Isolate* isolate, v8::IdleTask* task) override;
|
|
bool IdleTasksEnabled(v8::Isolate* isolate) override;
|
|
|
|
double MonotonicallyIncreasingTime() override;
|
|
double CurrentClockTimeMillis() override;
|
|
v8::TracingController* GetTracingController() override;
|
|
|
|
|
|
private:
|
|
V8Platform(const V8Platform&) = delete;
|
|
void operator=(const V8Platform&) = delete;
|
|
|
|
std::unique_ptr<v8::TracingController> tracing_controller_;
|
|
|
|
std::mutex foreground_task_runner_map_access_mutex;
|
|
std::map<v8::Isolate*, std::shared_ptr<ForegroundTaskRunner>> foreground_task_runner_map_;
|
|
|
|
std::unique_ptr<WorkerThreadsTaskRunner> worker_task_runner_;
|
|
|
|
public:
|
|
|
|
static V8Platform& Get();
|
|
};
|
|
|
|
}}
|