Commit b8e2b30a authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

Worker: Clarify thread affinity for improving code maintainability

To improve code maintainability, this CL clarifies thread affinity of
initialization and shutdown functions in worker classes. This does not change
any existing behavior.

Bug: 741227
Change-Id: I25fe7278130c90292b79cdd5607f10a0ef92f198
Reviewed-on: https://chromium-review.googlesource.com/567609
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486740}
parent 8b70da20
...@@ -53,7 +53,7 @@ Vector<RefPtr<DOMWrapperWorld>> CreateWorlds(v8::Isolate* isolate) { ...@@ -53,7 +53,7 @@ Vector<RefPtr<DOMWrapperWorld>> CreateWorlds(v8::Isolate* isolate) {
void WorkerThreadFunc(WorkerBackingThread* thread, void WorkerThreadFunc(WorkerBackingThread* thread,
RefPtr<WebTaskRunner> main_thread_task_runner) { RefPtr<WebTaskRunner> main_thread_task_runner) {
thread->Initialize(WorkerV8Settings::Default()); thread->InitializeOnBackingThread(WorkerV8Settings::Default());
// Worlds on the main thread should not be visible from the worker thread. // Worlds on the main thread should not be visible from the worker thread.
Vector<RefPtr<DOMWrapperWorld>> retrieved_worlds; Vector<RefPtr<DOMWrapperWorld>> retrieved_worlds;
...@@ -78,7 +78,7 @@ void WorkerThreadFunc(WorkerBackingThread* thread, ...@@ -78,7 +78,7 @@ void WorkerThreadFunc(WorkerBackingThread* thread,
} }
worlds.clear(); worlds.clear();
thread->Shutdown(); thread->ShutdownOnBackingThread();
main_thread_task_runner->PostTask(BLINK_FROM_HERE, main_thread_task_runner->PostTask(BLINK_FROM_HERE,
CrossThreadBind(&testing::ExitRunLoop)); CrossThreadBind(&testing::ExitRunLoop));
} }
......
...@@ -63,11 +63,12 @@ class MultiThreadedTest : public ::testing::Test { ...@@ -63,11 +63,12 @@ class MultiThreadedTest : public ::testing::Test {
WebTaskRunner* task_runner = WebTaskRunner* task_runner =
threads[i]->PlatformThread().GetWebTaskRunner(); threads[i]->PlatformThread().GetWebTaskRunner();
task_runner->PostTask( task_runner->PostTask(FROM_HERE,
FROM_HERE, CrossThreadBind(
CrossThreadBind( [](WebThreadSupportingGC* thread) {
[](WebThreadSupportingGC* thread) { thread->Initialize(); }, thread->InitializeOnThread();
CrossThreadUnretained(threads[i].get()))); },
CrossThreadUnretained(threads[i].get())));
for (int j = 0; j < callbacks_per_thread_; ++j) { for (int j = 0; j < callbacks_per_thread_; ++j) {
task_runner->PostTask(FROM_HERE, task_runner->PostTask(FROM_HERE,
...@@ -77,7 +78,7 @@ class MultiThreadedTest : public ::testing::Test { ...@@ -77,7 +78,7 @@ class MultiThreadedTest : public ::testing::Test {
task_runner->PostTask( task_runner->PostTask(
FROM_HERE, CrossThreadBind( FROM_HERE, CrossThreadBind(
[](WebThreadSupportingGC* thread, WaitableEvent* w) { [](WebThreadSupportingGC* thread, WaitableEvent* w) {
thread->Shutdown(); thread->ShutdownOnThread();
w->Signal(); w->Signal();
}, },
CrossThreadUnretained(threads[i].get()), CrossThreadUnretained(threads[i].get()),
......
...@@ -58,9 +58,12 @@ WorkerBackingThread::WorkerBackingThread(WebThread* thread, ...@@ -58,9 +58,12 @@ WorkerBackingThread::WorkerBackingThread(WebThread* thread,
WorkerBackingThread::~WorkerBackingThread() {} WorkerBackingThread::~WorkerBackingThread() {}
void WorkerBackingThread::Initialize(const WorkerV8Settings& settings) { void WorkerBackingThread::InitializeOnBackingThread(
const WorkerV8Settings& settings) {
DCHECK(backing_thread_->IsCurrentThread());
backing_thread_->InitializeOnThread();
DCHECK(!isolate_); DCHECK(!isolate_);
backing_thread_->Initialize();
isolate_ = V8PerIsolateData::Initialize( isolate_ = V8PerIsolateData::Initialize(
backing_thread_->PlatformThread().GetWebTaskRunner()); backing_thread_->PlatformThread().GetWebTaskRunner());
AddWorkerIsolate(isolate_); AddWorkerIsolate(isolate_);
...@@ -91,7 +94,8 @@ void WorkerBackingThread::Initialize(const WorkerV8Settings& settings) { ...@@ -91,7 +94,8 @@ void WorkerBackingThread::Initialize(const WorkerV8Settings& settings) {
WorkerV8Settings::AtomicsWaitMode::kAllow); WorkerV8Settings::AtomicsWaitMode::kAllow);
} }
void WorkerBackingThread::Shutdown() { void WorkerBackingThread::ShutdownOnBackingThread() {
DCHECK(backing_thread_->IsCurrentThread());
if (is_owning_thread_) if (is_owning_thread_)
Platform::Current()->WillStopWorkerThread(); Platform::Current()->WillStopWorkerThread();
...@@ -101,7 +105,7 @@ void WorkerBackingThread::Shutdown() { ...@@ -101,7 +105,7 @@ void WorkerBackingThread::Shutdown() {
// This statement runs only in tests. // This statement runs only in tests.
V8GCController::CollectAllGarbageForTesting(isolate_); V8GCController::CollectAllGarbageForTesting(isolate_);
} }
backing_thread_->Shutdown(); backing_thread_->ShutdownOnThread();
RemoveWorkerIsolate(isolate_); RemoveWorkerIsolate(isolate_);
V8PerIsolateData::Destroy(isolate_); V8PerIsolateData::Destroy(isolate_);
......
...@@ -20,14 +20,10 @@ class WebThread; ...@@ -20,14 +20,10 @@ class WebThread;
class WebThreadSupportingGC; class WebThreadSupportingGC;
struct WorkerV8Settings; struct WorkerV8Settings;
// WorkerBackingThread represents a WebThread with Oilpan and V8 potentially // WorkerBackingThread represents a WebThread with Oilpan and V8. A client of
// shared by multiple WebWorker scripts. A WebWorker needs to call initialize() // WorkerBackingThread (i.e., WorkerThread) needs to call
// to using V8 and Oilpan functionalities, and call shutdown() when the script // InitializeOnBackingThread() to use V8 and Oilpan functionalities, and call
// no longer needs the thread. // ShutdownOnBackingThread() when it no longer needs the thread.
// A WorkerBackingThread represents a WebThread while a WorkerThread corresponds
// to a web worker. There is one-to-one correspondence between WorkerThread and
// WorkerGlobalScope, but multiple WorkerThreads (i.e., multiple
// WorkerGlobalScopes) can share one WorkerBackingThread.
class CORE_EXPORT WorkerBackingThread final { class CORE_EXPORT WorkerBackingThread final {
public: public:
static std::unique_ptr<WorkerBackingThread> Create(const char* name) { static std::unique_ptr<WorkerBackingThread> Create(const char* name) {
...@@ -48,12 +44,12 @@ class CORE_EXPORT WorkerBackingThread final { ...@@ -48,12 +44,12 @@ class CORE_EXPORT WorkerBackingThread final {
~WorkerBackingThread(); ~WorkerBackingThread();
// initialize() and shutdown() attaches and detaches Oilpan and V8 to / from // InitializeOnBackingThread() and ShutdownOnBackingThread() attaches and
// the caller worker script, respectively. A worker script must not call // detaches Oilpan and V8 to / from the caller worker script, respectively.
// any function after calling shutdown(). // A worker script must not call any function after calling
// They should be called from |this| thread. // ShutdownOnBackingThread(). They should be called from |this| thread.
void Initialize(const WorkerV8Settings&); void InitializeOnBackingThread(const WorkerV8Settings&);
void Shutdown(); void ShutdownOnBackingThread();
WebThreadSupportingGC& BackingThread() { WebThreadSupportingGC& BackingThread() {
DCHECK(backing_thread_); DCHECK(backing_thread_);
......
...@@ -409,7 +409,7 @@ void WorkerThread::InitializeOnWorkerThread( ...@@ -409,7 +409,7 @@ void WorkerThread::InitializeOnWorkerThread(
MutexLocker lock(thread_state_mutex_); MutexLocker lock(thread_state_mutex_);
if (IsOwningBackingThread()) if (IsOwningBackingThread())
GetWorkerBackingThread().Initialize(v8_settings); GetWorkerBackingThread().InitializeOnBackingThread(v8_settings);
GetWorkerBackingThread().BackingThread().AddTaskObserver(this); GetWorkerBackingThread().BackingThread().AddTaskObserver(this);
console_message_storage_ = new ConsoleMessageStorage(); console_message_storage_ = new ConsoleMessageStorage();
...@@ -518,7 +518,7 @@ void WorkerThread::PerformShutdownOnWorkerThread() { ...@@ -518,7 +518,7 @@ void WorkerThread::PerformShutdownOnWorkerThread() {
global_scope_ = nullptr; global_scope_ = nullptr;
if (IsOwningBackingThread()) if (IsOwningBackingThread())
GetWorkerBackingThread().Shutdown(); GetWorkerBackingThread().ShutdownOnBackingThread();
// We must not touch workerBackingThread() from now on. // We must not touch workerBackingThread() from now on.
// Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed // Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed
......
...@@ -63,8 +63,8 @@ enum WorkerThreadStartMode { ...@@ -63,8 +63,8 @@ enum WorkerThreadStartMode {
// WorkerThread is a kind of WorkerBackingThread client. Each worker mechanism // WorkerThread is a kind of WorkerBackingThread client. Each worker mechanism
// can access the lower thread infrastructure via an implementation of this // can access the lower thread infrastructure via an implementation of this
// abstract class. Multiple WorkerThreads can share one WorkerBackingThread. // abstract class. Multiple WorkerThreads may share one WorkerBackingThread for
// See WorkerBackingThread.h for more details. // worklets.
// //
// WorkerThread start and termination must be initiated on the main thread and // WorkerThread start and termination must be initiated on the main thread and
// an actual task is executed on the worker thread. // an actual task is executed on the worker thread.
......
...@@ -92,7 +92,7 @@ class WorkletThreadHolder { ...@@ -92,7 +92,7 @@ class WorkletThreadHolder {
void InitializeOnWorkletThread() { void InitializeOnWorkletThread() {
MutexLocker locker(HolderInstanceMutex()); MutexLocker locker(HolderInstanceMutex());
DCHECK(!initialized_); DCHECK(!initialized_);
thread_->Initialize(WorkerV8Settings::Default()); thread_->InitializeOnBackingThread(WorkerV8Settings::Default());
initialized_ = true; initialized_ = true;
} }
...@@ -108,7 +108,7 @@ class WorkletThreadHolder { ...@@ -108,7 +108,7 @@ class WorkletThreadHolder {
} }
void ShutdownOnWorlketThread(WaitableEvent* waitable_event) { void ShutdownOnWorlketThread(WaitableEvent* waitable_event) {
thread_->Shutdown(); thread_->ShutdownOnBackingThread();
waitable_event->Signal(); waitable_event->Signal();
} }
......
...@@ -57,6 +57,7 @@ DataConsumerHandleTestUtil::Thread::~Thread() { ...@@ -57,6 +57,7 @@ DataConsumerHandleTestUtil::Thread::~Thread() {
} }
void DataConsumerHandleTestUtil::Thread::Initialize() { void DataConsumerHandleTestUtil::Thread::Initialize() {
DCHECK(thread_->IsCurrentThread());
if (initialization_policy_ >= kScriptExecution) { if (initialization_policy_ >= kScriptExecution) {
isolate_holder_ = isolate_holder_ =
WTF::MakeUnique<gin::IsolateHolder>(Platform::Current() WTF::MakeUnique<gin::IsolateHolder>(Platform::Current()
...@@ -66,7 +67,7 @@ void DataConsumerHandleTestUtil::Thread::Initialize() { ...@@ -66,7 +67,7 @@ void DataConsumerHandleTestUtil::Thread::Initialize() {
->ToSingleThreadTaskRunner()); ->ToSingleThreadTaskRunner());
GetIsolate()->Enter(); GetIsolate()->Enter();
} }
thread_->Initialize(); thread_->InitializeOnThread();
if (initialization_policy_ >= kScriptExecution) { if (initialization_policy_ >= kScriptExecution) {
v8::HandleScope handle_scope(GetIsolate()); v8::HandleScope handle_scope(GetIsolate());
script_state_ = ScriptState::Create( script_state_ = ScriptState::Create(
...@@ -81,12 +82,13 @@ void DataConsumerHandleTestUtil::Thread::Initialize() { ...@@ -81,12 +82,13 @@ void DataConsumerHandleTestUtil::Thread::Initialize() {
} }
void DataConsumerHandleTestUtil::Thread::Shutdown() { void DataConsumerHandleTestUtil::Thread::Shutdown() {
DCHECK(thread_->IsCurrentThread());
execution_context_ = nullptr; execution_context_ = nullptr;
if (script_state_) { if (script_state_) {
script_state_->DisposePerContextData(); script_state_->DisposePerContextData();
} }
script_state_ = nullptr; script_state_ = nullptr;
thread_->Shutdown(); thread_->ShutdownOnThread();
if (isolate_holder_) { if (isolate_holder_) {
GetIsolate()->Exit(); GetIsolate()->Exit();
GetIsolate()->RequestGarbageCollectionForTesting( GetIsolate()->RequestGarbageCollectionForTesting(
......
...@@ -67,7 +67,8 @@ void DatabaseThread::Start() { ...@@ -67,7 +67,8 @@ void DatabaseThread::Start() {
} }
void DatabaseThread::SetupDatabaseThread() { void DatabaseThread::SetupDatabaseThread() {
thread_->Initialize(); DCHECK(thread_->IsCurrentThread());
thread_->InitializeOnThread();
transaction_coordinator_ = new SQLTransactionCoordinator(); transaction_coordinator_ = new SQLTransactionCoordinator();
} }
...@@ -122,7 +123,8 @@ void DatabaseThread::CleanupDatabaseThread() { ...@@ -122,7 +123,8 @@ void DatabaseThread::CleanupDatabaseThread() {
} }
void DatabaseThread::CleanupDatabaseThreadCompleted() { void DatabaseThread::CleanupDatabaseThreadCompleted() {
thread_->Shutdown(); DCHECK(thread_->IsCurrentThread());
thread_->ShutdownOnThread();
if (cleanup_sync_) // Someone wanted to know when we were done cleaning up. if (cleanup_sync_) // Someone wanted to know when we were done cleaning up.
cleanup_sync_->Signal(); cleanup_sync_->Signal();
} }
......
...@@ -26,6 +26,7 @@ std::unique_ptr<WebThreadSupportingGC> WebThreadSupportingGC::CreateForThread( ...@@ -26,6 +26,7 @@ std::unique_ptr<WebThreadSupportingGC> WebThreadSupportingGC::CreateForThread(
WebThreadSupportingGC::WebThreadSupportingGC(const char* name, WebThreadSupportingGC::WebThreadSupportingGC(const char* name,
WebThread* thread) WebThread* thread)
: thread_(thread) { : thread_(thread) {
DCHECK(IsMainThread());
DCHECK(!name || !thread); DCHECK(!name || !thread);
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
// We call this regardless of whether an existing thread is given or not, // We call this regardless of whether an existing thread is given or not,
...@@ -41,17 +42,20 @@ WebThreadSupportingGC::WebThreadSupportingGC(const char* name, ...@@ -41,17 +42,20 @@ WebThreadSupportingGC::WebThreadSupportingGC(const char* name,
} }
WebThreadSupportingGC::~WebThreadSupportingGC() { WebThreadSupportingGC::~WebThreadSupportingGC() {
DCHECK(IsMainThread());
// WebThread's destructor blocks until all the tasks are processed. // WebThread's destructor blocks until all the tasks are processed.
owning_thread_.reset(); owning_thread_.reset();
MemoryCoordinator::UnregisterThread(thread_); MemoryCoordinator::UnregisterThread(thread_);
} }
void WebThreadSupportingGC::Initialize() { void WebThreadSupportingGC::InitializeOnThread() {
DCHECK(thread_->IsCurrentThread());
ThreadState::AttachCurrentThread(); ThreadState::AttachCurrentThread();
gc_task_runner_ = WTF::MakeUnique<GCTaskRunner>(thread_); gc_task_runner_ = WTF::MakeUnique<GCTaskRunner>(thread_);
} }
void WebThreadSupportingGC::Shutdown() { void WebThreadSupportingGC::ShutdownOnThread() {
DCHECK(thread_->IsCurrentThread());
#if defined(LEAK_SANITIZER) #if defined(LEAK_SANITIZER)
ThreadState::Current()->ReleaseStaticPersistentNodes(); ThreadState::Current()->ReleaseStaticPersistentNodes();
#endif #endif
......
...@@ -16,11 +16,12 @@ ...@@ -16,11 +16,12 @@
namespace blink { namespace blink {
// WebThreadSupportingGC wraps a WebThread and adds support for attaching // WebThreadSupportingGC wraps a WebThread and adds support for attaching
// to and detaching from the Blink GC infrastructure. The initialize method // to and detaching from the Blink GC infrastructure.
// must be called during initialization on the WebThread and before the //
// thread allocates any objects managed by the Blink GC. The shutdown // The initialize method must be called during initialization on the WebThread
// method must be called on the WebThread during shutdown when the thread // and before the thread allocates any objects managed by the Blink GC. The
// no longer needs to access objects managed by the Blink GC. // shutdown method must be called on the WebThread during shutdown when the
// thread no longer needs to access objects managed by the Blink GC.
// //
// WebThreadSupportingGC usually internally creates and owns WebThread unless // WebThreadSupportingGC usually internally creates and owns WebThread unless
// an existing WebThread is given via createForThread. // an existing WebThread is given via createForThread.
...@@ -67,8 +68,9 @@ class PLATFORM_EXPORT WebThreadSupportingGC final { ...@@ -67,8 +68,9 @@ class PLATFORM_EXPORT WebThreadSupportingGC final {
thread_->RemoveTaskObserver(observer); thread_->RemoveTaskObserver(observer);
} }
void Initialize(); // Must be called on the WebThread.
void Shutdown(); void InitializeOnThread();
void ShutdownOnThread();
WebThread& PlatformThread() const { WebThread& PlatformThread() const {
DCHECK(thread_); DCHECK(thread_);
......
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