#pragma once #include "v8.h" #include "libplatform/libplatform.h" #include #include #include #include #include #include #include #include namespace facebook { namespace v8runtime { class ForegroundTaskRunner : public v8::TaskRunner { public: ForegroundTaskRunner(std::shared_ptr queue):queue_(queue){} void PostTask(std::unique_ptr task) override; void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override { std::abort(); } void PostIdleTask(std::unique_ptr task) override { std::abort(); } bool IdleTasksEnabled() override { return false; }; private: std::shared_ptr queue_; }; class WorkerThreadsTaskRunner : public v8::TaskRunner { public: WorkerThreadsTaskRunner(); ~WorkerThreadsTaskRunner(); void PostTask(std::unique_ptr task) override; void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override; void PostIdleTask(std::unique_ptr task) override { std::abort(); } bool IdleTasksEnabled() override { return false; }; private: void WorkerFunc(); void TimerFunc(); private: using DelayedEntry = std::pair>; // 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, DelayedEntryCompare> delayed_task_queue_; std::queue> 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 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 queue, V8Runtime* runtime) : jsQueue_(queue), runtimeimpl_(runtime) {} std::shared_ptr jsQueue_; V8Runtime* runtimeimpl_; }; class V8Platform : public v8::Platform { public: explicit V8Platform(); ~V8Platform() override; int NumberOfWorkerThreads() override; std::shared_ptr GetForegroundTaskRunner(v8::Isolate* isolate) override; void CallOnWorkerThread(std::unique_ptr task) override; void CallDelayedOnWorkerThread(std::unique_ptr 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 tracing_controller_; std::mutex foreground_task_runner_map_access_mutex; std::map> foreground_task_runner_map_; std::unique_ptr worker_task_runner_; public: static V8Platform& Get(); }; }}