Commit 905318c7 authored by Omer Katz's avatar Omer Katz Committed by Commit Bot

Reland "cppgc: Provide jobs support through DefaultPlatform and TestPlatform"

This reverts commit 2221f090.

Reason for revert: fix in patchset 2

Original change's description:
> Revert "cppgc: Provide jobs support through DefaultPlatform and TestPlatform"
>
> This reverts commit 22c0fc8f.
>
> Reason for revert: https://ci.chromium.org/p/v8/builders/ci/V8%20Linux%20gcc/8712?
>
> Original change's description:
> > cppgc: Provide jobs support through DefaultPlatform and TestPlatform
> >
> > This CL extends cppgc::DefaultPlatform and TestPlatform to emulate
> > jobs using std::thread and v8::base::Thread respectively.
> > Jobs using these platform do not yield unless the job as been
> > cancelled. Additionally, the job priority is ignored.
> >
> > Bug: chromium:1056170
> > Change-Id: I72db1eef410d2be3d3e5ea7d4ece9e5584a451f2
> > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2416378
> > Commit-Queue: Omer Katz <omerkatz@chromium.org>
> > Reviewed-by: Anton Bikineev <bikineev@chromium.org>
> > Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#70139}
>
> TBR=mlippautz@chromium.org,bikineev@chromium.org,omerkatz@chromium.org
>
> Change-Id: Ic29235e3ab78a1b515a5b14b808e116a1ccffc0f
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: chromium:1056170
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2432087
> Reviewed-by: Francis McCabe <fgm@chromium.org>
> Commit-Queue: Francis McCabe <fgm@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#70142}

# Not skipping CQ checks because this is a reland.

Bug: chromium:1056170
Change-Id: Iaa8312da759ab97f646a9fb6144462a115393b5f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2431666Reviewed-by: 's avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70150}
parent 8ca2a7c8
...@@ -4331,6 +4331,7 @@ v8_source_set("cppgc_base") { ...@@ -4331,6 +4331,7 @@ v8_source_set("cppgc_base") {
"include/cppgc/visitor.h", "include/cppgc/visitor.h",
"include/v8config.h", "include/v8config.h",
"src/heap/cppgc/allocation.cc", "src/heap/cppgc/allocation.cc",
"src/heap/cppgc/default-job.h",
"src/heap/cppgc/default-platform.cc", "src/heap/cppgc/default-platform.cc",
"src/heap/cppgc/free-list.cc", "src/heap/cppgc/free-list.cc",
"src/heap/cppgc/free-list.h", "src/heap/cppgc/free-list.h",
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define INCLUDE_CPPGC_DEFAULT_PLATFORM_H_ #define INCLUDE_CPPGC_DEFAULT_PLATFORM_H_
#include <memory> #include <memory>
#include <thread> // NOLINT(build/c++11)
#include <vector> #include <vector>
#include "cppgc/platform.h" #include "cppgc/platform.h"
...@@ -14,6 +13,10 @@ ...@@ -14,6 +13,10 @@
namespace cppgc { namespace cppgc {
namespace internal {
class DefaultJob;
} // namespace internal
/** /**
* Default task runner implementation. Keep posted tasks in a list that can be * Default task runner implementation. Keep posted tasks in a list that can be
* processed by calling RunSingleTask() or RunUntilIdle(). * processed by calling RunSingleTask() or RunUntilIdle().
...@@ -61,6 +64,8 @@ class V8_EXPORT DefaultPlatform final : public Platform { ...@@ -61,6 +64,8 @@ class V8_EXPORT DefaultPlatform final : public Platform {
std::shared_ptr<cppgc::TaskRunner> GetForegroundTaskRunner() final; std::shared_ptr<cppgc::TaskRunner> GetForegroundTaskRunner() final;
// DefaultPlatform does not support job priorities. All jobs would be
// assigned the same priority regardless of the cppgc::TaskPriority parameter.
std::unique_ptr<cppgc::JobHandle> PostJob( std::unique_ptr<cppgc::JobHandle> PostJob(
cppgc::TaskPriority priority, cppgc::TaskPriority priority,
std::unique_ptr<cppgc::JobTask> job_task) final; std::unique_ptr<cppgc::JobTask> job_task) final;
...@@ -71,7 +76,7 @@ class V8_EXPORT DefaultPlatform final : public Platform { ...@@ -71,7 +76,7 @@ class V8_EXPORT DefaultPlatform final : public Platform {
private: private:
std::unique_ptr<PageAllocator> page_allocator_; std::unique_ptr<PageAllocator> page_allocator_;
std::shared_ptr<DefaultTaskRunner> foreground_task_runner_; std::shared_ptr<DefaultTaskRunner> foreground_task_runner_;
std::vector<std::shared_ptr<std::thread>> job_threads_; std::vector<std::shared_ptr<internal::DefaultJob>> jobs_;
}; };
} // namespace cppgc } // namespace cppgc
......
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_CPPGC_DEFAULT_JOB_H_
#define V8_HEAP_CPPGC_DEFAULT_JOB_H_
#include <atomic>
#include <map>
#include <memory>
#include <unordered_set>
#include <vector>
#include "include/cppgc/platform.h"
#include "src/base/logging.h"
#include "src/base/platform/mutex.h"
namespace cppgc {
namespace internal {
template <typename Job>
class DefaultJobFactory {
public:
static std::shared_ptr<Job> Create(std::unique_ptr<cppgc::JobTask> job_task) {
std::shared_ptr<Job> job =
std::make_shared<Job>(typename Job::Key(), std::move(job_task));
job->NotifyConcurrencyIncrease();
return job;
}
};
template <typename Thread>
class DefaultJobImpl {
public:
class JobDelegate;
class JobHandle;
class Key {
private:
Key() {}
template <typename Job>
friend class DefaultJobFactory;
};
DefaultJobImpl(Key, std::unique_ptr<cppgc::JobTask> job_task)
: job_task_(std::move(job_task)) {}
~DefaultJobImpl() {
Cancel();
DCHECK_EQ(0, active_threads_.load(std::memory_order_relaxed));
}
void NotifyConcurrencyIncrease();
void Join() {
for (std::shared_ptr<Thread>& thread : job_threads_) thread->Join();
job_threads_.clear();
can_run_.store(false, std::memory_order_relaxed);
}
void Cancel() {
can_run_.store(false, std::memory_order_relaxed);
Join();
}
bool IsCompleted() const { return !IsRunning(); }
bool IsRunning() const {
uint8_t active_threads = active_threads_.load(std::memory_order_relaxed);
return (active_threads + job_task_->GetMaxConcurrency(active_threads)) > 0;
}
bool CanRun() const { return can_run_.load(std::memory_order_relaxed); }
void RunJobTask() {
DCHECK_NOT_NULL(job_task_);
NotifyJobThreadStart();
JobDelegate delegate(this);
job_task_->Run(&delegate);
NotifyJobThreadEnd();
}
protected:
virtual std::shared_ptr<Thread> CreateThread(DefaultJobImpl*) = 0;
void NotifyJobThreadStart() {
active_threads_.fetch_add(1, std::memory_order_relaxed);
}
void NotifyJobThreadEnd() {
active_threads_.fetch_sub(1, std::memory_order_relaxed);
}
void GuaranteeAvailableIds(uint8_t max_threads) {
if (max_threads <= highest_thread_count_) return;
v8::base::MutexGuard guard(&ids_lock_);
while (highest_thread_count_ < max_threads) {
available_ids_.push_back(++highest_thread_count_);
}
}
std::unique_ptr<cppgc::JobTask> job_task_;
std::vector<std::shared_ptr<Thread>> job_threads_;
std::atomic_bool can_run_{true};
std::atomic_uint8_t active_threads_{0};
// Task id management.
v8::base::Mutex ids_lock_;
std::vector<uint8_t> available_ids_;
uint8_t highest_thread_count_ = -1;
};
template <typename Thread>
class DefaultJobImpl<Thread>::JobDelegate final : public cppgc::JobDelegate {
public:
explicit JobDelegate(DefaultJobImpl* job) : job_(job) {}
~JobDelegate() { ReleaseTaskId(); }
bool ShouldYield() override { return !job_->CanRun(); }
void NotifyConcurrencyIncrease() override {
job_->NotifyConcurrencyIncrease();
}
uint8_t GetTaskId() override {
AcquireTaskId();
return job_thread_id_;
}
private:
void AcquireTaskId() {
if (job_thread_id_ != kInvalidTaskId) return;
v8::base::MutexGuard guard(&job_->ids_lock_);
job_thread_id_ = job_->available_ids_.back();
DCHECK_NE(kInvalidTaskId, job_thread_id_);
job_->available_ids_.pop_back();
}
void ReleaseTaskId() {
if (job_thread_id_ == kInvalidTaskId) return;
v8::base::MutexGuard guard(&job_->ids_lock_);
job_->available_ids_.push_back(job_thread_id_);
}
DefaultJobImpl* const job_;
static constexpr uint8_t kInvalidTaskId = std::numeric_limits<uint8_t>::max();
uint8_t job_thread_id_ = kInvalidTaskId;
};
template <typename Thread>
void DefaultJobImpl<Thread>::NotifyConcurrencyIncrease() {
DCHECK(CanRun());
static const size_t kMaxThreads = Thread::GetMaxSupportedConcurrency();
uint8_t current_active_threads =
active_threads_.load(std::memory_order_relaxed);
size_t max_threads = std::min(
kMaxThreads, job_task_->GetMaxConcurrency(current_active_threads));
if (current_active_threads >= max_threads) return;
DCHECK_LT(max_threads, std::numeric_limits<uint8_t>::max());
GuaranteeAvailableIds(max_threads);
for (uint8_t new_threads = max_threads - current_active_threads;
new_threads > 0; --new_threads) {
std::shared_ptr<Thread> thread = CreateThread(this);
job_threads_.push_back(thread);
}
}
template <typename Thread>
class DefaultJobImpl<Thread>::JobHandle final : public cppgc::JobHandle {
public:
explicit JobHandle(std::shared_ptr<DefaultJobImpl> job)
: job_(std::move(job)) {
DCHECK_NOT_NULL(job_);
}
void NotifyConcurrencyIncrease() override {
job_->NotifyConcurrencyIncrease();
}
void Join() override { job_->Join(); }
void Cancel() override { job_->Cancel(); }
bool IsCompleted() override { return job_->IsCompleted(); }
bool IsRunning() override { return job_->IsRunning(); }
private:
std::shared_ptr<DefaultJobImpl> job_;
};
} // namespace internal
} // namespace cppgc
#endif // V8_HEAP_CPPGC_DEFAULT_JOB_H_
...@@ -9,30 +9,44 @@ ...@@ -9,30 +9,44 @@
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/page-allocator.h" #include "src/base/page-allocator.h"
#include "src/base/sys-info.h"
#include "src/heap/cppgc/default-job.h"
namespace cppgc { namespace cppgc {
namespace { namespace internal {
// Simple implementation of JobTask based on std::thread. // Default implementation of Jobs based on std::thread.
class DefaultJobHandle : public JobHandle { namespace {
class DefaultJobThread final : private std::thread {
public: public:
explicit DefaultJobHandle(std::shared_ptr<std::thread> thread) template <typename Function>
: thread_(std::move(thread)) {} explicit DefaultJobThread(Function function)
: std::thread(std::move(function)) {}
~DefaultJobThread() { DCHECK(!joinable()); }
void NotifyConcurrencyIncrease() override {} void Join() { join(); }
void Join() override {
if (thread_->joinable()) thread_->join(); static size_t GetMaxSupportedConcurrency() {
return v8::base::SysInfo::NumberOfProcessors() - 1;
} }
void Cancel() override { Join(); } };
bool IsCompleted() override { return !IsRunning(); } } // namespace
bool IsRunning() override { return thread_->joinable(); }
class DefaultJob final : public DefaultJobImpl<DefaultJobThread> {
public:
DefaultJob(Key key, std::unique_ptr<cppgc::JobTask> job_task)
: DefaultJobImpl(key, std::move(job_task)) {}
private: std::shared_ptr<DefaultJobThread> CreateThread(DefaultJobImpl* job) final {
std::shared_ptr<std::thread> thread_; return std::make_shared<DefaultJobThread>([job = this] {
DCHECK_NOT_NULL(job);
job->RunJobTask();
});
}
}; };
} // namespace } // namespace internal
void DefaultTaskRunner::PostTask(std::unique_ptr<cppgc::Task> task) { void DefaultTaskRunner::PostTask(std::unique_ptr<cppgc::Task> task) {
tasks_.push_back(std::move(task)); tasks_.push_back(std::move(task));
...@@ -108,19 +122,11 @@ std::shared_ptr<cppgc::TaskRunner> DefaultPlatform::GetForegroundTaskRunner() { ...@@ -108,19 +122,11 @@ std::shared_ptr<cppgc::TaskRunner> DefaultPlatform::GetForegroundTaskRunner() {
std::unique_ptr<cppgc::JobHandle> DefaultPlatform::PostJob( std::unique_ptr<cppgc::JobHandle> DefaultPlatform::PostJob(
cppgc::TaskPriority priority, std::unique_ptr<cppgc::JobTask> job_task) { cppgc::TaskPriority priority, std::unique_ptr<cppgc::JobTask> job_task) {
auto thread = std::make_shared<std::thread>([task = std::move(job_task)] { std::shared_ptr<internal::DefaultJob> job =
class SimpleDelegate final : public cppgc::JobDelegate { internal::DefaultJobFactory<internal::DefaultJob>::Create(
public: std::move(job_task));
bool ShouldYield() override { return false; } jobs_.push_back(job);
void NotifyConcurrencyIncrease() override {} return std::make_unique<internal::DefaultJob::JobHandle>(std::move(job));
uint8_t GetTaskId() override { return 0; }
bool IsJoiningThread() const override { return false; }
} delegate;
if (task) task->Run(&delegate);
});
job_threads_.push_back(thread);
return std::make_unique<DefaultJobHandle>(std::move(thread));
} }
void DefaultPlatform::WaitAllForegroundTasks() { void DefaultPlatform::WaitAllForegroundTasks() {
...@@ -128,10 +134,10 @@ void DefaultPlatform::WaitAllForegroundTasks() { ...@@ -128,10 +134,10 @@ void DefaultPlatform::WaitAllForegroundTasks() {
} }
void DefaultPlatform::WaitAllBackgroundTasks() { void DefaultPlatform::WaitAllBackgroundTasks() {
for (auto& thread : job_threads_) { for (auto& job : jobs_) {
thread->join(); job->Join();
} }
job_threads_.clear(); jobs_.clear();
} }
} // namespace cppgc } // namespace cppgc
...@@ -146,7 +146,7 @@ MarkerBase::IncrementalMarkingTask::IncrementalMarkingTask( ...@@ -146,7 +146,7 @@ MarkerBase::IncrementalMarkingTask::IncrementalMarkingTask(
// static // static
MarkerBase::IncrementalMarkingTask::Handle MarkerBase::IncrementalMarkingTask::Handle
MarkerBase::IncrementalMarkingTask::Post(v8::TaskRunner* runner, MarkerBase::IncrementalMarkingTask::Post(cppgc::TaskRunner* runner,
MarkerBase* marker) { MarkerBase* marker) {
// Incremental GC is possible only via the GCInvoker, so getting here // Incremental GC is possible only via the GCInvoker, so getting here
// guarantees that either non-nestable tasks or conservative stack // guarantees that either non-nestable tasks or conservative stack
......
...@@ -99,13 +99,13 @@ class V8_EXPORT_PRIVATE MarkerBase { ...@@ -99,13 +99,13 @@ class V8_EXPORT_PRIVATE MarkerBase {
bool IncrementalMarkingStepForTesting(MarkingConfig::StackState); bool IncrementalMarkingStepForTesting(MarkingConfig::StackState);
class IncrementalMarkingTask final : public v8::Task { class IncrementalMarkingTask final : public cppgc::Task {
public: public:
using Handle = SingleThreadedHandle; using Handle = SingleThreadedHandle;
IncrementalMarkingTask(MarkerBase*, MarkingConfig::StackState); IncrementalMarkingTask(MarkerBase*, MarkingConfig::StackState);
static Handle Post(v8::TaskRunner*, MarkerBase*); static Handle Post(cppgc::TaskRunner*, MarkerBase*);
private: private:
void Run() final; void Run() final;
...@@ -156,7 +156,7 @@ class V8_EXPORT_PRIVATE MarkerBase { ...@@ -156,7 +156,7 @@ class V8_EXPORT_PRIVATE MarkerBase {
MarkingConfig config_ = MarkingConfig::Default(); MarkingConfig config_ = MarkingConfig::Default();
cppgc::Platform* platform_; cppgc::Platform* platform_;
std::shared_ptr<v8::TaskRunner> foreground_task_runner_; std::shared_ptr<cppgc::TaskRunner> foreground_task_runner_;
IncrementalMarkingTask::Handle incremental_marking_handle_; IncrementalMarkingTask::Handle incremental_marking_handle_;
MarkingWorklists marking_worklists_; MarkingWorklists marking_worklists_;
......
...@@ -384,14 +384,14 @@ class MutatorThreadSweeper final : private HeapVisitor<MutatorThreadSweeper> { ...@@ -384,14 +384,14 @@ class MutatorThreadSweeper final : private HeapVisitor<MutatorThreadSweeper> {
cppgc::Platform* platform_; cppgc::Platform* platform_;
}; };
class ConcurrentSweepTask final : public v8::JobTask, class ConcurrentSweepTask final : public cppgc::JobTask,
private HeapVisitor<ConcurrentSweepTask> { private HeapVisitor<ConcurrentSweepTask> {
friend class HeapVisitor<ConcurrentSweepTask>; friend class HeapVisitor<ConcurrentSweepTask>;
public: public:
explicit ConcurrentSweepTask(SpaceStates* states) : states_(states) {} explicit ConcurrentSweepTask(SpaceStates* states) : states_(states) {}
void Run(v8::JobDelegate* delegate) final { void Run(cppgc::JobDelegate* delegate) final {
for (SpaceState& state : *states_) { for (SpaceState& state : *states_) {
while (auto page = state.unswept_pages.Pop()) { while (auto page = state.unswept_pages.Pop()) {
Traverse(*page); Traverse(*page);
...@@ -525,14 +525,14 @@ class Sweeper::SweeperImpl final { ...@@ -525,14 +525,14 @@ class Sweeper::SweeperImpl final {
} }
private: private:
class IncrementalSweepTask : public v8::IdleTask { class IncrementalSweepTask : public cppgc::IdleTask {
public: public:
using Handle = SingleThreadedHandle; using Handle = SingleThreadedHandle;
explicit IncrementalSweepTask(SweeperImpl* sweeper) explicit IncrementalSweepTask(SweeperImpl* sweeper)
: sweeper_(sweeper), handle_(Handle::NonEmptyTag{}) {} : sweeper_(sweeper), handle_(Handle::NonEmptyTag{}) {}
static Handle Post(SweeperImpl* sweeper, v8::TaskRunner* runner) { static Handle Post(SweeperImpl* sweeper, cppgc::TaskRunner* runner) {
auto task = std::make_unique<IncrementalSweepTask>(sweeper); auto task = std::make_unique<IncrementalSweepTask>(sweeper);
auto handle = task->GetHandle(); auto handle = task->GetHandle();
runner->PostIdleTask(std::move(task)); runner->PostIdleTask(std::move(task));
...@@ -573,7 +573,7 @@ class Sweeper::SweeperImpl final { ...@@ -573,7 +573,7 @@ class Sweeper::SweeperImpl final {
if (!platform_) return; if (!platform_) return;
concurrent_sweeper_handle_ = platform_->PostJob( concurrent_sweeper_handle_ = platform_->PostJob(
v8::TaskPriority::kUserVisible, cppgc::TaskPriority::kUserVisible,
std::make_unique<ConcurrentSweepTask>(&space_states_)); std::make_unique<ConcurrentSweepTask>(&space_states_));
} }
...@@ -593,9 +593,9 @@ class Sweeper::SweeperImpl final { ...@@ -593,9 +593,9 @@ class Sweeper::SweeperImpl final {
StatsCollector* stats_collector_; StatsCollector* stats_collector_;
SpaceStates space_states_; SpaceStates space_states_;
cppgc::Platform* platform_; cppgc::Platform* platform_;
std::shared_ptr<v8::TaskRunner> foreground_task_runner_; std::shared_ptr<cppgc::TaskRunner> foreground_task_runner_;
IncrementalSweepTask::Handle incremental_sweeper_handle_; IncrementalSweepTask::Handle incremental_sweeper_handle_;
std::unique_ptr<v8::JobHandle> concurrent_sweeper_handle_; std::unique_ptr<cppgc::JobHandle> concurrent_sweeper_handle_;
bool is_in_progress_ = false; bool is_in_progress_ = false;
}; };
......
...@@ -6,29 +6,68 @@ ...@@ -6,29 +6,68 @@
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/base/platform/time.h" #include "src/base/platform/time.h"
#include "src/heap/cppgc/default-job.h"
namespace cppgc { namespace cppgc {
namespace internal { namespace internal {
namespace testing { namespace testing {
void TestTaskRunner::PostTask(std::unique_ptr<v8::Task> task) { namespace {
class TestJobThread final : public v8::base::Thread {
public:
using id = uint8_t;
explicit TestJobThread(TestJob* job) : Thread(Options("job")), job_(job) {}
void Run() final;
static size_t GetMaxSupportedConcurrency() { return 4u; }
private:
TestJob* const job_;
};
} // namespace
// Default implementation of Jobs based on std::thread.
class TestJob final : public DefaultJobImpl<TestJobThread> {
public:
explicit TestJob(Key key, std::unique_ptr<cppgc::JobTask> job_task)
: DefaultJobImpl(key, std::move(job_task)) {}
std::shared_ptr<TestJobThread> CreateThread(DefaultJobImpl* job) final {
std::shared_ptr<TestJobThread> thread =
std::make_shared<TestJobThread>(this);
const bool thread_started = thread->Start();
USE(thread_started);
DCHECK(thread_started);
return thread;
}
};
void TestJobThread::Run() {
DCHECK_NOT_NULL(job_);
job_->RunJobTask();
}
void TestTaskRunner::PostTask(std::unique_ptr<cppgc::Task> task) {
tasks_.push_back(std::move(task)); tasks_.push_back(std::move(task));
} }
void TestTaskRunner::PostNonNestableTask(std::unique_ptr<v8::Task> task) { void TestTaskRunner::PostNonNestableTask(std::unique_ptr<cppgc::Task> task) {
PostTask(std::move(task)); PostTask(std::move(task));
} }
void TestTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, double) { void TestTaskRunner::PostDelayedTask(std::unique_ptr<cppgc::Task> task,
double) {
PostTask(std::move(task)); PostTask(std::move(task));
} }
void TestTaskRunner::PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task, void TestTaskRunner::PostNonNestableDelayedTask(
double) { std::unique_ptr<cppgc::Task> task, double) {
PostTask(std::move(task)); PostTask(std::move(task));
} }
void TestTaskRunner::PostIdleTask(std::unique_ptr<v8::IdleTask> task) { void TestTaskRunner::PostIdleTask(std::unique_ptr<cppgc::IdleTask> task) {
idle_tasks_.push_back(std::move(task)); idle_tasks_.push_back(std::move(task));
} }
...@@ -62,36 +101,19 @@ void TestTaskRunner::RunUntilIdle() { ...@@ -62,36 +101,19 @@ void TestTaskRunner::RunUntilIdle() {
idle_tasks_.clear(); idle_tasks_.clear();
} }
class TestPlatform::TestJobHandle : public v8::JobHandle {
public:
explicit TestJobHandle(const std::shared_ptr<JobThread>& thread)
: thread_(thread) {
const bool success = thread_->Start();
USE(success);
}
void NotifyConcurrencyIncrease() override {}
void Join() override { thread_->Join(); }
void Cancel() override { Join(); }
bool IsCompleted() override { return true; }
bool IsRunning() override { return true; }
private:
std::shared_ptr<JobThread> thread_;
};
TestPlatform::TestPlatform() TestPlatform::TestPlatform()
: foreground_task_runner_(std::make_unique<TestTaskRunner>()) {} : foreground_task_runner_(std::make_unique<TestTaskRunner>()) {}
TestPlatform::~TestPlatform() V8_NOEXCEPT { WaitAllBackgroundTasks(); } TestPlatform::~TestPlatform() V8_NOEXCEPT { WaitAllBackgroundTasks(); }
std::unique_ptr<v8::JobHandle> TestPlatform::PostJob( std::unique_ptr<cppgc::JobHandle> TestPlatform::PostJob(
v8::TaskPriority, std::unique_ptr<v8::JobTask> job_task) { cppgc::TaskPriority, std::unique_ptr<cppgc::JobTask> job_task) {
if (AreBackgroundTasksDisabled()) return {}; if (AreBackgroundTasksDisabled()) return {};
auto thread = std::make_shared<JobThread>(std::move(job_task)); std::shared_ptr<TestJob> job =
job_threads_.push_back(thread); DefaultJobFactory<TestJob>::Create(std::move(job_task));
return std::make_unique<TestJobHandle>(std::move(thread)); jobs_.push_back(job);
return std::make_unique<TestJob::JobHandle>(std::move(job));
} }
double TestPlatform::MonotonicallyIncreasingTime() { double TestPlatform::MonotonicallyIncreasingTime() {
...@@ -104,10 +126,10 @@ void TestPlatform::WaitAllForegroundTasks() { ...@@ -104,10 +126,10 @@ void TestPlatform::WaitAllForegroundTasks() {
} }
void TestPlatform::WaitAllBackgroundTasks() { void TestPlatform::WaitAllBackgroundTasks() {
for (auto& thread : job_threads_) { for (auto& job : jobs_) {
thread->Join(); job->Join();
} }
job_threads_.clear(); jobs_.clear();
} }
TestPlatform::DisableBackgroundTasksScope::DisableBackgroundTasksScope( TestPlatform::DisableBackgroundTasksScope::DisableBackgroundTasksScope(
......
...@@ -16,20 +16,22 @@ namespace cppgc { ...@@ -16,20 +16,22 @@ namespace cppgc {
namespace internal { namespace internal {
namespace testing { namespace testing {
class TestTaskRunner : public v8::TaskRunner { class TestJob;
class TestTaskRunner : public cppgc::TaskRunner {
public: public:
void PostTask(std::unique_ptr<v8::Task> task) override; void PostTask(std::unique_ptr<cppgc::Task> task) override;
void PostDelayedTask(std::unique_ptr<v8::Task> task, double) override; void PostDelayedTask(std::unique_ptr<cppgc::Task> task, double) override;
bool NonNestableTasksEnabled() const override { return true; } bool NonNestableTasksEnabled() const override { return true; }
void PostNonNestableTask(std::unique_ptr<v8::Task> task) override; void PostNonNestableTask(std::unique_ptr<cppgc::Task> task) override;
bool NonNestableDelayedTasksEnabled() const override { return true; } bool NonNestableDelayedTasksEnabled() const override { return true; }
void PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task, void PostNonNestableDelayedTask(std::unique_ptr<cppgc::Task> task,
double) override; double) override;
bool IdleTasksEnabled() override { return true; } bool IdleTasksEnabled() override { return true; }
void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; void PostIdleTask(std::unique_ptr<cppgc::IdleTask> task) override;
bool RunSingleTask(); bool RunSingleTask();
bool RunSingleIdleTask(double duration_in_seconds); bool RunSingleIdleTask(double duration_in_seconds);
...@@ -37,8 +39,8 @@ class TestTaskRunner : public v8::TaskRunner { ...@@ -37,8 +39,8 @@ class TestTaskRunner : public v8::TaskRunner {
void RunUntilIdle(); void RunUntilIdle();
private: private:
std::vector<std::unique_ptr<v8::Task>> tasks_; std::vector<std::unique_ptr<cppgc::Task>> tasks_;
std::vector<std::unique_ptr<v8::IdleTask>> idle_tasks_; std::vector<std::unique_ptr<cppgc::IdleTask>> idle_tasks_;
}; };
class TestPlatform : public Platform { class TestPlatform : public Platform {
...@@ -57,12 +59,14 @@ class TestPlatform : public Platform { ...@@ -57,12 +59,14 @@ class TestPlatform : public Platform {
PageAllocator* GetPageAllocator() override { return &page_allocator_; } PageAllocator* GetPageAllocator() override { return &page_allocator_; }
std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() override { std::shared_ptr<cppgc::TaskRunner> GetForegroundTaskRunner() override {
return foreground_task_runner_; return foreground_task_runner_;
} }
std::unique_ptr<v8::JobHandle> PostJob( // TestPlatform does not support job priorities. All jobs would be assigned
v8::TaskPriority, std::unique_ptr<v8::JobTask> job_task) override; // the same priority regardless of the cppgc::TaskPriority parameter.
std::unique_ptr<cppgc::JobHandle> PostJob(
cppgc::TaskPriority, std::unique_ptr<cppgc::JobTask> job_task) override;
double MonotonicallyIncreasingTime() override; double MonotonicallyIncreasingTime() override;
...@@ -70,49 +74,13 @@ class TestPlatform : public Platform { ...@@ -70,49 +74,13 @@ class TestPlatform : public Platform {
void WaitAllBackgroundTasks(); void WaitAllBackgroundTasks();
private: private:
class TestJobHandle;
class WorkerThread : public v8::base::Thread {
public:
explicit WorkerThread(std::unique_ptr<v8::Task> task)
: Thread(Options("worker")), task_(std::move(task)) {}
void Run() override {
if (task_) std::move(task_)->Run();
}
private:
std::unique_ptr<v8::Task> task_;
};
class JobThread : public v8::base::Thread {
public:
explicit JobThread(std::unique_ptr<v8::JobTask> task)
: Thread(Options("job")), task_(std::move(task)) {}
void Run() override {
class JobDelegate : public v8::JobDelegate {
public:
bool ShouldYield() override { return false; }
void NotifyConcurrencyIncrease() override {}
uint8_t GetTaskId() override { return 0; }
bool IsJoiningThread() const override { return false; }
} delegate;
if (task_) task_->Run(&delegate);
}
private:
std::unique_ptr<v8::JobTask> task_;
};
bool AreBackgroundTasksDisabled() const { bool AreBackgroundTasksDisabled() const {
return disabled_background_tasks_ > 0; return disabled_background_tasks_ > 0;
} }
v8::base::PageAllocator page_allocator_; v8::base::PageAllocator page_allocator_;
std::shared_ptr<TestTaskRunner> foreground_task_runner_; std::shared_ptr<TestTaskRunner> foreground_task_runner_;
std::vector<std::shared_ptr<JobThread>> job_threads_; std::vector<std::shared_ptr<TestJob>> jobs_;
size_t disabled_background_tasks_ = 0; size_t disabled_background_tasks_ = 0;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment