Commit 9deeac46 authored by Yuta Kitamura's avatar Yuta Kitamura Committed by Commit Bot

Move thread-related functionalities in Platform to Thread.

This CL moves the most of implementation for Thread in Platform to
Thread, so the Platform would contain less implementation (ideally,
Platform should be a pure interface to embedders).

Previously the global state of threads was stored in Platform, and
this CL moves it to Thread. Now the thread-local storage for Blink
threads and the main and compositor thread objects are stored as
the global variable in thread.cc. This way, the threads state is
completely separated from Platform. Old threading functions in
Platform are deprecated now, and they will be migrated to Thread ones
later.

Due to those changes, some test utilities need to be updated. As the
state of threads is not stored in Platform, the tests that need to
override their main thread have to do that by themselves. To
facilitate this, two new utility classes, ScopedMainThreadOverrider
and ScopedSchedulerOverrider, are introduced, and TestingPlatform-
SupportWithCustomScheduler is removed in favor of the new utilities.

Bug: 826203
Change-Id: Ieb702dc85b7ffd75991055038f1165c2bfd7d058
Reviewed-on: https://chromium-review.googlesource.com/c/1273115
Commit-Queue: Yuta Kitamura <yutak@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599133}
parent 68084907
...@@ -1160,7 +1160,7 @@ void RenderThreadImpl::SetResourceDispatcherDelegate( ...@@ -1160,7 +1160,7 @@ void RenderThreadImpl::SetResourceDispatcherDelegate(
} }
void RenderThreadImpl::InitializeCompositorThread() { void RenderThreadImpl::InitializeCompositorThread() {
blink_platform_impl_->InitializeCompositorThread(); blink_platform_impl_->CreateAndSetCompositorThread();
compositor_task_runner_ = blink_platform_impl_->CompositorThreadTaskRunner(); compositor_task_runner_ = blink_platform_impl_->CompositorThreadTaskRunner();
compositor_task_runner_->PostTask( compositor_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
......
...@@ -167,6 +167,12 @@ class BLINK_PLATFORM_EXPORT Platform { ...@@ -167,6 +167,12 @@ class BLINK_PLATFORM_EXPORT Platform {
// You should not pass in a Platform object that is not fully instantiated. // You should not pass in a Platform object that is not fully instantiated.
static void SetCurrentPlatformForTesting(Platform*); static void SetCurrentPlatformForTesting(Platform*);
// This sets up a minimally viable implementation of blink::Thread without
// changing the current Platform. This is essentially a workaround for the
// initialization order in ScopedUnittestsEnvironmentSetup, and nobody else
// should use this.
static void CreateMainThreadForTesting();
// These are dirty workaround for tests requiring the main thread task runner // These are dirty workaround for tests requiring the main thread task runner
// from a non-main thread. If your test needs base::ScopedTaskEnvironment // from a non-main thread. If your test needs base::ScopedTaskEnvironment
// and a non-main thread may call MainThread()->GetTaskRunner(), call // and a non-main thread may call MainThread()->GetTaskRunner(), call
...@@ -428,38 +434,34 @@ class BLINK_PLATFORM_EXPORT Platform { ...@@ -428,38 +434,34 @@ class BLINK_PLATFORM_EXPORT Platform {
// Threads ------------------------------------------------------- // Threads -------------------------------------------------------
// blink::Thread creation is no longer customizable in Platform. // Most of threading functionality has moved to blink::Thread. The functions
// CreateThread() always creates a new physical thread for Blink. // in Platform are deprecated; use the counterpart in blink::Thread as noted
// Platform maintains the thread-local storage containing each blink::Thread // below.
// object, so that CurrentThread() could return the correct thread object.
//
// TODO(yutak): These non-virtual functions should be moved to somewhere
// else, because they no longer require embedder's implementation.
// Creates a new thread. This may be called from a non-main thread (e.g. // DEPRECATED: Use Thread::CreateThread() instead.
// nested Web workers).
std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&); std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&);
// Creates a WebAudio-specific thread with the elevated priority. Do NOT use // DEPRECATED: Use Thread::CreateWebAudioThread() instead.
// for any other purpose.
std::unique_ptr<Thread> CreateWebAudioThread(); std::unique_ptr<Thread> CreateWebAudioThread();
// Create and initialize the compositor thread. The thread is saved in // DEPRECATED: Use Thread::Current() instead.
// Platform, and will be accessible through CompositorThread().
void InitializeCompositorThread();
// Returns an interface to the current thread.
Thread* CurrentThread(); Thread* CurrentThread();
// Returns an interface to the main thread. // DEPRECATED: Use Thread::MainThread() instead.
Thread* MainThread(); Thread* MainThread();
// Returns an interface to the compositor thread. This can be null if the // DEPRECATED: Use Thread::CompositorThread() instead.
// renderer was created with threaded rendering disabled.
Thread* CompositorThread(); Thread* CompositorThread();
// The two compositor-related functions below are called by the embedder.
// TODO(yutak): Perhaps we should move these to somewhere else?
// Create and initialize the compositor thread. After this function
// completes, you can access CompositorThreadTaskRunner().
void CreateAndSetCompositorThread();
// Returns the task runner of the compositor thread. This is available // Returns the task runner of the compositor thread. This is available
// once InitializeCompositorThread() is called. // once CreateAndSetCompositorThread() is called.
scoped_refptr<base::SingleThreadTaskRunner> CompositorThreadTaskRunner(); scoped_refptr<base::SingleThreadTaskRunner> CompositorThreadTaskRunner();
// This is called after the compositor thread is created, so the embedder // This is called after the compositor thread is created, so the embedder
...@@ -766,28 +768,9 @@ class BLINK_PLATFORM_EXPORT Platform { ...@@ -766,28 +768,9 @@ class BLINK_PLATFORM_EXPORT Platform {
// runs during Chromium's build step). // runs during Chromium's build step).
virtual bool IsTakingV8ContextSnapshot() { return false; } virtual bool IsTakingV8ContextSnapshot() { return false; }
protected:
Thread* main_thread_;
private: private:
static void InitializeCommon(Platform* platform); static void InitializeCommon(Platform* platform,
std::unique_ptr<Thread> main_thread);
void WaitUntilThreadTLSUpdate(Thread*);
void UpdateThreadTLS(Thread* thread, base::WaitableEvent* event);
// Platform owns the main thread in most cases. The pointer value is the same
// as main_thread_ if this variable is non-null.
//
// This variable is null if (and only if) ScopedTestingPlatformSupport<>
// overrides the old Platform. In this case, main_thread_ points to the old
// Platform's main thread. See testing_platform_support.h for this.
std::unique_ptr<Thread> owned_main_thread_;
std::unique_ptr<Thread> compositor_thread_;
// We can't use WTF stuff here. Ultimately these should go away (see comments
// near CreateThread()), though.
base::ThreadLocalStorage::Slot current_thread_slot_;
}; };
} // namespace blink } // namespace blink
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" #include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h"
#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" #include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/blink/renderer/platform/wtf/time.h" #include "third_party/blink/renderer/platform/wtf/time.h"
...@@ -74,7 +74,7 @@ class IdleDeadlineTest : public testing::Test { ...@@ -74,7 +74,7 @@ class IdleDeadlineTest : public testing::Test {
WTF::ScopedMockClock clock_; WTF::ScopedMockClock clock_;
}; };
TEST_F(IdleDeadlineTest, deadlineInFuture) { TEST_F(IdleDeadlineTest, DeadlineInFuture) {
IdleDeadline* deadline = IdleDeadline* deadline =
IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25), IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
IdleDeadline::CallbackType::kCalledWhenIdle); IdleDeadline::CallbackType::kCalledWhenIdle);
...@@ -82,18 +82,16 @@ TEST_F(IdleDeadlineTest, deadlineInFuture) { ...@@ -82,18 +82,16 @@ TEST_F(IdleDeadlineTest, deadlineInFuture) {
EXPECT_FLOAT_EQ(250.0, deadline->timeRemaining()); EXPECT_FLOAT_EQ(250.0, deadline->timeRemaining());
} }
TEST_F(IdleDeadlineTest, deadlineInPast) { TEST_F(IdleDeadlineTest, DeadlineInPast) {
IdleDeadline* deadline = IdleDeadline* deadline =
IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(0.75), IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(0.75),
IdleDeadline::CallbackType::kCalledWhenIdle); IdleDeadline::CallbackType::kCalledWhenIdle);
EXPECT_FLOAT_EQ(0, deadline->timeRemaining()); EXPECT_FLOAT_EQ(0, deadline->timeRemaining());
} }
TEST_F(IdleDeadlineTest, yieldForHighPriorityWork) { TEST_F(IdleDeadlineTest, YieldForHighPriorityWork) {
MockIdleDeadlineScheduler scheduler; MockIdleDeadlineScheduler scheduler;
ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, ScopedSchedulerOverrider scheduler_overrider(&scheduler);
ThreadScheduler*>
platform(&scheduler);
IdleDeadline* deadline = IdleDeadline* deadline =
IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25), IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
......
...@@ -6,12 +6,11 @@ ...@@ -6,12 +6,11 @@
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h"
#include "third_party/blink/renderer/core/dom/idle_request_options.h" #include "third_party/blink/renderer/core/dom/idle_request_options.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h" #include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" #include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h"
#include "third_party/blink/renderer/platform/wtf/time.h" #include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink { namespace blink {
...@@ -94,9 +93,7 @@ class ScriptedIdleTaskControllerTest : public testing::Test { ...@@ -94,9 +93,7 @@ class ScriptedIdleTaskControllerTest : public testing::Test {
TEST_F(ScriptedIdleTaskControllerTest, RunCallback) { TEST_F(ScriptedIdleTaskControllerTest, RunCallback) {
MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::DONT_YIELD); MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::DONT_YIELD);
ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, ScopedSchedulerOverrider scheduler_overrider(&scheduler);
ThreadScheduler*>
platform(&scheduler);
NullExecutionContext execution_context; NullExecutionContext execution_context;
ScriptedIdleTaskController* controller = ScriptedIdleTaskController* controller =
...@@ -117,9 +114,7 @@ TEST_F(ScriptedIdleTaskControllerTest, RunCallback) { ...@@ -117,9 +114,7 @@ TEST_F(ScriptedIdleTaskControllerTest, RunCallback) {
TEST_F(ScriptedIdleTaskControllerTest, DontRunCallbackWhenAskedToYield) { TEST_F(ScriptedIdleTaskControllerTest, DontRunCallbackWhenAskedToYield) {
MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::YIELD); MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::YIELD);
ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, ScopedSchedulerOverrider scheduler_overrider(&scheduler);
ThreadScheduler*>
platform(&scheduler);
NullExecutionContext execution_context; NullExecutionContext execution_context;
ScriptedIdleTaskController* controller = ScriptedIdleTaskController* controller =
......
...@@ -1574,15 +1574,17 @@ jumbo_static_library("test_support") { ...@@ -1574,15 +1574,17 @@ jumbo_static_library("test_support") {
"testing/picture_matchers.h", "testing/picture_matchers.h",
"testing/scoped_fake_plugin_registry.cc", "testing/scoped_fake_plugin_registry.cc",
"testing/scoped_fake_plugin_registry.h", "testing/scoped_fake_plugin_registry.h",
"testing/scoped_main_thread_overrider.cc",
"testing/scoped_main_thread_overrider.h",
"testing/scoped_mocked_url.cc", "testing/scoped_mocked_url.cc",
"testing/scoped_mocked_url.h", "testing/scoped_mocked_url.h",
"testing/scoped_scheduler_overrider.cc",
"testing/scoped_scheduler_overrider.h",
"testing/stub_graphics_layer_client.h", "testing/stub_graphics_layer_client.h",
"testing/test_paint_artifact.cc", "testing/test_paint_artifact.cc",
"testing/test_paint_artifact.h", "testing/test_paint_artifact.h",
"testing/testing_platform_support.cc", "testing/testing_platform_support.cc",
"testing/testing_platform_support.h", "testing/testing_platform_support.h",
"testing/testing_platform_support_with_custom_scheduler.cc",
"testing/testing_platform_support_with_custom_scheduler.h",
"testing/testing_platform_support_with_mock_scheduler.cc", "testing/testing_platform_support_with_mock_scheduler.cc",
"testing/testing_platform_support_with_mock_scheduler.h", "testing/testing_platform_support_with_mock_scheduler.h",
"testing/testing_platform_support_with_web_rtc.cc", "testing/testing_platform_support_with_web_rtc.cc",
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <memory> #include <memory>
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -113,7 +112,7 @@ static void CallOnMainThreadFunction(WTF::MainThreadFunction function, ...@@ -113,7 +112,7 @@ static void CallOnMainThreadFunction(WTF::MainThreadFunction function,
CrossThreadBind(function, CrossThreadUnretained(context))); CrossThreadBind(function, CrossThreadUnretained(context)));
} }
Platform::Platform() : main_thread_(nullptr) { Platform::Platform() {
WTF::Partitions::Initialize(MaxObservedSizeFunction); WTF::Partitions::Initialize(MaxObservedSizeFunction);
} }
...@@ -170,27 +169,22 @@ void Platform::Initialize( ...@@ -170,27 +169,22 @@ void Platform::Initialize(
DCHECK(!g_platform); DCHECK(!g_platform);
DCHECK(platform); DCHECK(platform);
g_platform = platform; g_platform = platform;
g_platform->owned_main_thread_ = main_thread_scheduler->CreateMainThread(); InitializeCommon(platform, main_thread_scheduler->CreateMainThread());
g_platform->main_thread_ = g_platform->owned_main_thread_.get();
DCHECK(!g_platform->current_thread_slot_.Get());
g_platform->current_thread_slot_.Set(g_platform->main_thread_);
InitializeCommon(platform);
} }
void Platform::CreateMainThreadAndInitialize(Platform* platform) { void Platform::CreateMainThreadAndInitialize(Platform* platform) {
DCHECK(!g_platform); DCHECK(!g_platform);
DCHECK(platform); DCHECK(platform);
g_platform = platform; g_platform = platform;
g_platform->owned_main_thread_ = std::make_unique<SimpleMainThread>(); InitializeCommon(platform, std::make_unique<SimpleMainThread>());
g_platform->main_thread_ = g_platform->owned_main_thread_.get();
DCHECK(!g_platform->current_thread_slot_.Get());
g_platform->current_thread_slot_.Set(g_platform->main_thread_);
InitializeCommon(platform);
} }
void Platform::InitializeCommon(Platform* platform) { void Platform::InitializeCommon(Platform* platform,
std::unique_ptr<Thread> main_thread) {
WTF::Initialize(CallOnMainThreadFunction); WTF::Initialize(CallOnMainThreadFunction);
Thread::SetMainThread(std::move(main_thread));
ProcessHeap::Init(); ProcessHeap::Init();
MemoryCoordinator::Initialize(); MemoryCoordinator::Initialize();
if (base::ThreadTaskRunnerHandle::IsSet()) { if (base::ThreadTaskRunnerHandle::IsSet()) {
...@@ -208,63 +202,45 @@ void Platform::InitializeCommon(Platform* platform) { ...@@ -208,63 +202,45 @@ void Platform::InitializeCommon(Platform* platform) {
FontFamilyNames::init(); FontFamilyNames::init();
InitializePlatformLanguage(); InitializePlatformLanguage();
// TODO(ssid): remove this check after fixing crbug.com/486782. DCHECK(!g_gc_task_runner);
if (g_platform->main_thread_) { g_gc_task_runner = new GCTaskRunner(Thread::MainThread());
DCHECK(!g_gc_task_runner); base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
g_gc_task_runner = new GCTaskRunner(g_platform->main_thread_); PartitionAllocMemoryDumpProvider::Instance(), "PartitionAlloc",
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( base::ThreadTaskRunnerHandle::Get());
PartitionAllocMemoryDumpProvider::Instance(), "PartitionAlloc", base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
base::ThreadTaskRunnerHandle::Get()); FontCacheMemoryDumpProvider::Instance(), "FontCaches",
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( base::ThreadTaskRunnerHandle::Get());
FontCacheMemoryDumpProvider::Instance(), "FontCaches", base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
base::ThreadTaskRunnerHandle::Get()); MemoryCacheDumpProvider::Instance(), "MemoryCache",
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( base::ThreadTaskRunnerHandle::Get());
MemoryCacheDumpProvider::Instance(), "MemoryCache", base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
base::ThreadTaskRunnerHandle::Get()); InstanceCountersMemoryDumpProvider::Instance(), "BlinkObjectCounters",
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( base::ThreadTaskRunnerHandle::Get());
InstanceCountersMemoryDumpProvider::Instance(), "BlinkObjectCounters",
base::ThreadTaskRunnerHandle::Get());
}
RendererResourceCoordinator::Initialize(); RendererResourceCoordinator::Initialize();
} }
void Platform::SetCurrentPlatformForTesting(Platform* platform) { void Platform::SetCurrentPlatformForTesting(Platform* platform) {
DCHECK(platform); DCHECK(platform);
// The overriding platform does not necessarily own the main thread
// (owned_main_thread_ may be null), but must have a pointer to a valid
// main thread object (which may be from the overridden platform).
//
// If the new platform's main_thread_ is null, that means we need to
// create a new main thread for it. This happens only in
// ScopedUnittestsEnvironmentSetup's constructor, which bypasses
// Platform::Initialize().
if (!platform->main_thread_) {
platform->owned_main_thread_ = std::make_unique<SimpleMainThread>();
platform->main_thread_ = platform->owned_main_thread_.get();
}
// Set only the main thread to TLS for the new platform. This is OK for the
// testing purposes. The TLS slot may already be set when
// ScopedTestingPlatformSupport tries to revert to the old platform.
if (!platform->current_thread_slot_.Get())
platform->current_thread_slot_.Set(platform->main_thread_);
g_platform = platform; g_platform = platform;
} }
void Platform::CreateMainThreadForTesting() {
DCHECK(!Thread::MainThread());
Thread::SetMainThread(std::make_unique<SimpleMainThread>());
}
void Platform::SetMainThreadTaskRunnerForTesting() { void Platform::SetMainThreadTaskRunnerForTesting() {
DCHECK(WTF::IsMainThread()); DCHECK(WTF::IsMainThread());
DCHECK(g_platform->main_thread_->IsSimpleMainThread()); DCHECK(Thread::MainThread()->IsSimpleMainThread());
static_cast<SimpleMainThread*>(g_platform->main_thread_) static_cast<SimpleMainThread*>(Thread::MainThread())
->SetMainThreadTaskRunnerForTesting(base::ThreadTaskRunnerHandle::Get()); ->SetMainThreadTaskRunnerForTesting(base::ThreadTaskRunnerHandle::Get());
} }
void Platform::UnsetMainThreadTaskRunnerForTesting() { void Platform::UnsetMainThreadTaskRunnerForTesting() {
DCHECK(WTF::IsMainThread()); DCHECK(WTF::IsMainThread());
DCHECK(g_platform->main_thread_->IsSimpleMainThread()); DCHECK(Thread::MainThread()->IsSimpleMainThread());
static_cast<SimpleMainThread*>(g_platform->main_thread_) static_cast<SimpleMainThread*>(Thread::MainThread())
->SetMainThreadTaskRunnerForTesting(nullptr); ->SetMainThreadTaskRunnerForTesting(nullptr);
} }
...@@ -273,11 +249,11 @@ Platform* Platform::Current() { ...@@ -273,11 +249,11 @@ Platform* Platform::Current() {
} }
Thread* Platform::MainThread() { Thread* Platform::MainThread() {
return main_thread_; return Thread::MainThread();
} }
Thread* Platform::CurrentThread() { Thread* Platform::CurrentThread() {
return static_cast<Thread*>(current_thread_slot_.Get()); return Thread::Current();
} }
service_manager::Connector* Platform::GetConnector() { service_manager::Connector* Platform::GetConnector() {
...@@ -305,57 +281,19 @@ std::unique_ptr<WebStorageNamespace> Platform::CreateSessionStorageNamespace( ...@@ -305,57 +281,19 @@ std::unique_ptr<WebStorageNamespace> Platform::CreateSessionStorageNamespace(
std::unique_ptr<Thread> Platform::CreateThread( std::unique_ptr<Thread> Platform::CreateThread(
const ThreadCreationParams& params) { const ThreadCreationParams& params) {
std::unique_ptr<scheduler::WebThreadBase> thread = return Thread::CreateThread(params);
scheduler::WebThreadBase::CreateWorkerThread(params);
thread->Init();
WaitUntilThreadTLSUpdate(thread.get());
return std::move(thread);
} }
std::unique_ptr<Thread> Platform::CreateWebAudioThread() { std::unique_ptr<Thread> Platform::CreateWebAudioThread() {
ThreadCreationParams params(WebThreadType::kWebAudioThread); return Thread::CreateWebAudioThread();
// WebAudio uses a thread with |DISPLAY| priority to avoid glitch when the }
// system is under the high pressure. Note that the main browser thread also
// runs with same priority. (see: crbug.com/734539) void Platform::CreateAndSetCompositorThread() {
params.thread_options.priority = base::ThreadPriority::DISPLAY; Thread::CreateAndSetCompositorThread();
return CreateThread(params);
}
void Platform::WaitUntilThreadTLSUpdate(Thread* thread) {
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
// This cross-thread posting is guaranteed to be safe.
PostCrossThreadTask(*thread->GetTaskRunner(), FROM_HERE,
CrossThreadBind(&Platform::UpdateThreadTLS,
WTF::CrossThreadUnretained(this),
WTF::CrossThreadUnretained(thread),
WTF::CrossThreadUnretained(&event)));
event.Wait();
}
void Platform::UpdateThreadTLS(Thread* thread, base::WaitableEvent* event) {
DCHECK(!current_thread_slot_.Get());
current_thread_slot_.Set(thread);
event->Signal();
}
void Platform::InitializeCompositorThread() {
DCHECK(!compositor_thread_);
ThreadCreationParams params(WebThreadType::kCompositorThread);
#if defined(OS_ANDROID)
params.thread_options.priority = base::ThreadPriority::DISPLAY;
#endif
std::unique_ptr<scheduler::WebThreadBase> compositor_thread =
scheduler::WebThreadBase::CreateCompositorThread(params);
compositor_thread->Init();
WaitUntilThreadTLSUpdate(compositor_thread.get());
compositor_thread_ = std::move(compositor_thread);
SetDisplayThreadPriority(compositor_thread_->ThreadId());
} }
Thread* Platform::CompositorThread() { Thread* Platform::CompositorThread() {
return compositor_thread_.get(); return Thread::CompositorThread();
} }
scoped_refptr<base::SingleThreadTaskRunner> scoped_refptr<base::SingleThreadTaskRunner>
......
...@@ -5,8 +5,15 @@ ...@@ -5,8 +5,15 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/child/webthread_base.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#if defined(OS_WIN) #if defined(OS_WIN)
#include <windows.h> #include <windows.h>
...@@ -16,6 +23,46 @@ ...@@ -16,6 +23,46 @@
namespace blink { namespace blink {
namespace {
// Thread-local storage for "blink::Thread"s.
Thread*& ThreadTLSSlot() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(WTF::ThreadSpecific<Thread*>, thread_tls_slot,
());
return *thread_tls_slot;
}
// Update the threads TLS on the newly created thread.
void UpdateThreadTLS(Thread* thread, base::WaitableEvent* event) {
ThreadTLSSlot() = thread;
event->Signal();
}
// Post a task to register |thread| to the TLS, and wait until it gets actually
// registered. This is called on a thread that created |thread| (not on
// |thread|.)
void UpdateThreadTLSAndWait(Thread* thread) {
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
PostCrossThreadTask(
*thread->GetTaskRunner(), FROM_HERE,
CrossThreadBind(&UpdateThreadTLS, WTF::CrossThreadUnretained(thread),
WTF::CrossThreadUnretained(&event)));
event.Wait();
}
std::unique_ptr<Thread>& GetMainThread() {
DEFINE_STATIC_LOCAL(std::unique_ptr<Thread>, main_thread, ());
return main_thread;
}
std::unique_ptr<Thread>& GetCompositorThread() {
DEFINE_STATIC_LOCAL(std::unique_ptr<Thread>, compositor_thread, ());
return compositor_thread;
}
} // namespace
ThreadCreationParams::ThreadCreationParams(WebThreadType thread_type) ThreadCreationParams::ThreadCreationParams(WebThreadType thread_type)
: thread_type(thread_type), : thread_type(thread_type),
name(GetNameForThreadType(thread_type)), name(GetNameForThreadType(thread_type)),
...@@ -33,6 +80,59 @@ ThreadCreationParams& ThreadCreationParams::SetFrameOrWorkerScheduler( ...@@ -33,6 +80,59 @@ ThreadCreationParams& ThreadCreationParams::SetFrameOrWorkerScheduler(
return *this; return *this;
} }
std::unique_ptr<Thread> Thread::CreateThread(
const ThreadCreationParams& params) {
std::unique_ptr<scheduler::WebThreadBase> thread =
scheduler::WebThreadBase::CreateWorkerThread(params);
thread->Init();
UpdateThreadTLSAndWait(thread.get());
return std::move(thread);
}
std::unique_ptr<Thread> Thread::CreateWebAudioThread() {
ThreadCreationParams params(WebThreadType::kWebAudioThread);
// WebAudio uses a thread with |DISPLAY| priority to avoid glitch when the
// system is under the high pressure. Note that the main browser thread also
// runs with same priority. (see: crbug.com/734539)
params.thread_options.priority = base::ThreadPriority::DISPLAY;
return CreateThread(params);
}
void Thread::CreateAndSetCompositorThread() {
DCHECK(!GetCompositorThread());
ThreadCreationParams params(WebThreadType::kCompositorThread);
#if defined(OS_ANDROID)
params.thread_options.priority = base::ThreadPriority::DISPLAY;
#endif
std::unique_ptr<scheduler::WebThreadBase> compositor_thread =
scheduler::WebThreadBase::CreateCompositorThread(params);
compositor_thread->Init();
UpdateThreadTLSAndWait(compositor_thread.get());
GetCompositorThread() = std::move(compositor_thread);
Platform::Current()->SetDisplayThreadPriority(
GetCompositorThread()->ThreadId());
}
Thread* Thread::Current() {
return ThreadTLSSlot();
}
Thread* Thread::MainThread() {
return GetMainThread().get();
}
Thread* Thread::CompositorThread() {
return GetCompositorThread().get();
}
std::unique_ptr<Thread> Thread::SetMainThread(
std::unique_ptr<Thread> main_thread) {
ThreadTLSSlot() = main_thread.get();
std::swap(GetMainThread(), main_thread);
return main_thread;
}
#if defined(OS_WIN) #if defined(OS_WIN)
static_assert(sizeof(blink::PlatformThreadId) >= sizeof(DWORD), static_assert(sizeof(blink::PlatformThreadId) >= sizeof(DWORD),
"size of platform thread id is too small"); "size of platform thread id is too small");
......
...@@ -70,7 +70,8 @@ struct PLATFORM_EXPORT ThreadCreationParams { ...@@ -70,7 +70,8 @@ struct PLATFORM_EXPORT ThreadCreationParams {
// run. // run.
class PLATFORM_EXPORT Thread { class PLATFORM_EXPORT Thread {
public: public:
friend class Platform; // For IsSimpleMainThread(). friend class Platform; // For SetMainThread() and IsSimpleMainThread().
friend class ScopedMainThreadOverrider; // For SetMainThread().
// An IdleTask is expected to complete before the deadline it is passed. // An IdleTask is expected to complete before the deadline it is passed.
using IdleTask = base::OnceCallback<void(base::TimeTicks deadline)>; using IdleTask = base::OnceCallback<void(base::TimeTicks deadline)>;
...@@ -82,6 +83,28 @@ class PLATFORM_EXPORT Thread { ...@@ -82,6 +83,28 @@ class PLATFORM_EXPORT Thread {
virtual void DidProcessTask() = 0; virtual void DidProcessTask() = 0;
}; };
// Creates a new thread. This may be called from a non-main thread (e.g.
// nested Web workers).
static std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&);
// Creates a WebAudio-specific thread with the elevated priority. Do NOT use
// for any other purpose.
static std::unique_ptr<Thread> CreateWebAudioThread();
// Create and save (as a global variable) the compositor thread. The thread
// will be accessible through CompositorThread().
static void CreateAndSetCompositorThread();
// Return an interface to the current thread.
static Thread* Current();
// Return an interface to the main thread.
static Thread* MainThread();
// Return an interface to the compositor thread (if initialized). This can be
// null if the renderer was created with threaded rendering disabled.
static Thread* CompositorThread();
// DEPRECATED: Returns a task runner bound to the underlying scheduler's // DEPRECATED: Returns a task runner bound to the underlying scheduler's
// default task queue. // default task queue.
// //
...@@ -118,6 +141,13 @@ class PLATFORM_EXPORT Thread { ...@@ -118,6 +141,13 @@ class PLATFORM_EXPORT Thread {
virtual ~Thread() = default; virtual ~Thread() = default;
private: private:
// For Platform and ScopedMainThreadOverrider. Return the thread object
// previously set (if any).
//
// This is done this way because we need to be able to "override" the main
// thread temporarily for ScopedTestingPlatformSupport.
static std::unique_ptr<Thread> SetMainThread(std::unique_ptr<Thread>);
// This is used to identify the actual Thread instance. This should be // This is used to identify the actual Thread instance. This should be
// used only in Platform, and other users should ignore this. // used only in Platform, and other users should ignore this.
virtual bool IsSimpleMainThread() const { return false; } virtual bool IsSimpleMainThread() const { return false; }
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h"
namespace blink {
ScopedMainThreadOverrider::ScopedMainThreadOverrider(
std::unique_ptr<Thread> main_thread)
: original_main_thread_(Thread::SetMainThread(std::move(main_thread))) {}
ScopedMainThreadOverrider::~ScopedMainThreadOverrider() {
Thread::SetMainThread(std::move(original_main_thread_));
}
} // namespace blink
// Copyright 2018 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_
#include <memory>
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
namespace blink {
// This class instance lets you override the main thread (of type blink::Thread)
// temporarily. This is useful when you want to change the main thread scheduler
// during a test (see ScopedSchedulerOverrider).
//
// When ScopedMainThreadOverrider goes out of scope, the main thread is
// reverted back to the original one, and the main thread object passed in
// the constructor gets destructed.
class ScopedMainThreadOverrider final {
public:
explicit ScopedMainThreadOverrider(std::unique_ptr<Thread> main_thread);
~ScopedMainThreadOverrider();
private:
std::unique_ptr<Thread> original_main_thread_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_
...@@ -2,9 +2,8 @@ ...@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" #include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h" #include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink { namespace blink {
...@@ -29,16 +28,10 @@ class ThreadWithCustomScheduler : public Thread { ...@@ -29,16 +28,10 @@ class ThreadWithCustomScheduler : public Thread {
} // namespace } // namespace
TestingPlatformSupportWithCustomScheduler:: ScopedSchedulerOverrider::ScopedSchedulerOverrider(ThreadScheduler* scheduler)
TestingPlatformSupportWithCustomScheduler(ThreadScheduler* scheduler) : main_thread_overrider_(
: thread_(std::make_unique<ThreadWithCustomScheduler>(scheduler)) { std::make_unique<ThreadWithCustomScheduler>(scheduler)) {}
// If main_thread_ is set, Platform::SetCurrentPlatformForTesting() properly
// sets up the platform so Platform::CurrentThread() would return the ScopedSchedulerOverrider::~ScopedSchedulerOverrider() {}
// thread specified here.
main_thread_ = thread_.get();
}
TestingPlatformSupportWithCustomScheduler::
~TestingPlatformSupportWithCustomScheduler() {}
} // namespace blink } // namespace blink
// Copyright 2018 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h"
namespace blink {
// A utility which lets you inject your custom implementation of ThreadScheduler
// on the main thread. This class sets up a very simple instance of
// blink::Thread and overrides the global main thread using ScopedMainThread-
// Overrider. Multi-thread is not supported.
class ScopedSchedulerOverrider final {
public:
// |scheduler| must be owned by the caller.
explicit ScopedSchedulerOverrider(ThreadScheduler* scheduler);
~ScopedSchedulerOverrider();
private:
ScopedMainThreadOverrider main_thread_overrider_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_
...@@ -96,7 +96,6 @@ TestingPlatformSupport::TestingPlatformSupport() ...@@ -96,7 +96,6 @@ TestingPlatformSupport::TestingPlatformSupport()
interface_provider_(new TestingInterfaceProvider) { interface_provider_(new TestingInterfaceProvider) {
DCHECK(old_platform_); DCHECK(old_platform_);
DCHECK(WTF::IsMainThread()); DCHECK(WTF::IsMainThread());
main_thread_ = old_platform_->CurrentThread();
} }
TestingPlatformSupport::~TestingPlatformSupport() { TestingPlatformSupport::~TestingPlatformSupport() {
...@@ -159,12 +158,22 @@ ScopedUnittestsEnvironmentSetup::ScopedUnittestsEnvironmentSetup(int argc, ...@@ -159,12 +158,22 @@ ScopedUnittestsEnvironmentSetup::ScopedUnittestsEnvironmentSetup(int argc,
base::DiscardableMemoryAllocator::SetInstance( base::DiscardableMemoryAllocator::SetInstance(
discardable_memory_allocator_.get()); discardable_memory_allocator_.get());
// TODO(yutak): The initialization steps below are essentially a subset of
// Platform::Initialize() steps with a few modifications for tests.
// We really shouldn't have those initialization steps in two places,
// because they are a very fragile piece of code (the initialization order
// is so sensitive) and we want it to be consistent between tests and
// production. Fix this someday.
dummy_platform_ = std::make_unique<Platform>(); dummy_platform_ = std::make_unique<Platform>();
Platform::SetCurrentPlatformForTesting(dummy_platform_.get()); Platform::SetCurrentPlatformForTesting(dummy_platform_.get());
WTF::Partitions::Initialize(nullptr); WTF::Partitions::Initialize(nullptr);
WTF::Initialize(nullptr); WTF::Initialize(nullptr);
// This must be called after WTF::Initialize(), because ThreadSpecific<>
// used in this function depends on WTF::IsMainThread().
Platform::CreateMainThreadForTesting();
testing_platform_support_ = std::make_unique<TestingPlatformSupport>(); testing_platform_support_ = std::make_unique<TestingPlatformSupport>();
Platform::SetCurrentPlatformForTesting(testing_platform_support_.get()); Platform::SetCurrentPlatformForTesting(testing_platform_support_.get());
......
// Copyright 2018 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_
#include <memory>
#include "base/macros.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
// Test environment where you can inject your custom implementation of
// ThreadScheduler on the main thread. Multi-thread is not supported.
//
// You would probably like to use this with ScopedTestingPlatformSupport
// class template. See testing_platform_support.h for details.
namespace blink {
class TestingPlatformSupportWithCustomScheduler
: public TestingPlatformSupport {
public:
// |scheduler| must be owned by the caller.
explicit TestingPlatformSupportWithCustomScheduler(
ThreadScheduler* scheduler);
~TestingPlatformSupportWithCustomScheduler() override;
private:
std::unique_ptr<Thread> thread_;
DISALLOW_COPY_AND_ASSIGN(TestingPlatformSupportWithCustomScheduler);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_
...@@ -27,8 +27,8 @@ TestingPlatformSupportWithMockScheduler:: ...@@ -27,8 +27,8 @@ TestingPlatformSupportWithMockScheduler::
scheduler_ = std::make_unique<scheduler::MainThreadSchedulerImpl>( scheduler_ = std::make_unique<scheduler::MainThreadSchedulerImpl>(
std::move(sequence_manager), base::nullopt); std::move(sequence_manager), base::nullopt);
thread_ = scheduler_->CreateMainThread(); main_thread_overrider_ = std::make_unique<ScopedMainThreadOverrider>(
main_thread_ = thread_.get(); scheduler_->CreateMainThread());
// Set the work batch size to one so TakePendingTasks behaves as expected. // Set the work batch size to one so TakePendingTasks behaves as expected.
scheduler_->GetSchedulerHelperForTesting()->SetWorkBatchSizeForTesting(1); scheduler_->GetSchedulerHelperForTesting()->SetWorkBatchSizeForTesting(1);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "base/test/test_mock_time_task_runner.h" #include "base/test/test_mock_time_task_runner.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h"
...@@ -36,6 +37,8 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport { ...@@ -36,6 +37,8 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
TestingPlatformSupportWithMockScheduler(); TestingPlatformSupportWithMockScheduler();
~TestingPlatformSupportWithMockScheduler() override; ~TestingPlatformSupportWithMockScheduler() override;
std::unique_ptr<Thread> CreateMainThread();
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner() { scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner() {
return test_task_runner_; return test_task_runner_;
} }
...@@ -77,7 +80,7 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport { ...@@ -77,7 +80,7 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
std::unique_ptr<scheduler::MainThreadSchedulerImpl> scheduler_; std::unique_ptr<scheduler::MainThreadSchedulerImpl> scheduler_;
base::sequence_manager::SequenceManager* base::sequence_manager::SequenceManager*
sequence_manager_; // Owned by scheduler_. sequence_manager_; // Owned by scheduler_.
std::unique_ptr<Thread> thread_; std::unique_ptr<ScopedMainThreadOverrider> main_thread_overrider_;
}; };
} // namespace blink } // namespace blink
......
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