diff options
author | dgrogan@chromium.org <dgrogan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-13 08:18:51 +0000 |
---|---|---|
committer | dgrogan@chromium.org <dgrogan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-13 08:18:51 +0000 |
commit | 0213480a48c9d02f15ad80e5bc670303c65ea11b (patch) | |
tree | cbaa434b1c315e5fca93a89cd600d2a475b4f1fe /webkit | |
parent | 6b6e7ee27ce2b3beccebbcb3dc8ca75bb1dfa067 (diff) | |
download | chromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.zip chromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.tar.gz chromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.tar.bz2 |
Track webcore worker message loops in chromium.
BUG=106265
TEST=
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=114157
Review URL: http://codereview.chromium.org/8785013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114192 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 | ||||
-rw-r--r-- | webkit/glue/webkitplatformsupport_impl.cc | 13 | ||||
-rw-r--r-- | webkit/glue/webkitplatformsupport_impl.h | 5 | ||||
-rw-r--r-- | webkit/glue/worker_task_runner.cc | 103 | ||||
-rw-r--r-- | webkit/glue/worker_task_runner.h | 59 | ||||
-rw-r--r-- | webkit/glue/worker_task_runner_unittest.cc | 56 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gypi | 1 |
7 files changed, 239 insertions, 0 deletions
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index 2c049b8..aa95004 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -436,6 +436,8 @@ 'web_io_operators.h', 'window_open_disposition.h', 'window_open_disposition.cc', + 'worker_task_runner.cc', + 'worker_task_runner.h', # These files used to be built in the webcore target, but moved here # since part of glue. diff --git a/webkit/glue/webkitplatformsupport_impl.cc b/webkit/glue/webkitplatformsupport_impl.cc index fd3759a..e8ddd15 100644 --- a/webkit/glue/webkitplatformsupport_impl.cc +++ b/webkit/glue/webkitplatformsupport_impl.cc @@ -41,6 +41,7 @@ #include "webkit/glue/websocketstreamhandle_impl.h" #include "webkit/glue/webthread_impl.h" #include "webkit/glue/weburlloader_impl.h" +#include "webkit/glue/worker_task_runner.h" #include "webkit/media/audio_decoder.h" #include "webkit/plugins/npapi/plugin_instance.h" #include "webkit/plugins/webplugininfo.h" @@ -686,4 +687,16 @@ void WebKitPlatformSupportImpl::DestroyCurrentThread(void* thread) { delete impl; } +void WebKitPlatformSupportImpl::didStartWorkerRunLoop( + const WebKit::WebWorkerRunLoop& runLoop) { + WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance(); + worker_task_runner->OnWorkerRunLoopStarted(runLoop); +} + +void WebKitPlatformSupportImpl::didStopWorkerRunLoop( + const WebKit::WebWorkerRunLoop& runLoop) { + WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance(); + worker_task_runner->OnWorkerRunLoopStopped(runLoop); +} + } // namespace webkit_glue diff --git a/webkit/glue/webkitplatformsupport_impl.h b/webkit/glue/webkitplatformsupport_impl.h index 75f8baa..02a7266 100644 --- a/webkit/glue/webkitplatformsupport_impl.h +++ b/webkit/glue/webkitplatformsupport_impl.h @@ -124,6 +124,11 @@ class WEBKIT_GLUE_EXPORT WebKitPlatformSupportImpl : void SuspendSharedTimer(); void ResumeSharedTimer(); + virtual void didStartWorkerRunLoop( + const WebKit::WebWorkerRunLoop& runLoop) OVERRIDE; + virtual void didStopWorkerRunLoop( + const WebKit::WebWorkerRunLoop& runLoop) OVERRIDE; + private: void DoTimeout() { if (shared_timer_func_ && !shared_timer_suspended_) diff --git a/webkit/glue/worker_task_runner.cc b/webkit/glue/worker_task_runner.cc new file mode 100644 index 0000000..3836e61 --- /dev/null +++ b/webkit/glue/worker_task_runner.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2011 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 "base/callback.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "webkit/glue/worker_task_runner.h" + +using WebKit::WebWorkerRunLoop; + +namespace { + +class RunClosureTask : public WebWorkerRunLoop::Task { + public: + RunClosureTask(const base::Closure& task) : task_(task) {} + virtual ~RunClosureTask() {} + virtual void Run() { + task_.Run(); + } + private: + base::Closure task_; +}; + +} // unnamed namespace + +namespace webkit_glue { + +struct WorkerTaskRunner::ThreadLocalState { + ThreadLocalState(int id, const WebWorkerRunLoop& loop) + : id_(id), run_loop_(loop) { + } + int id_; + WebWorkerRunLoop run_loop_; + ObserverList<WorkerTaskRunner::Observer> stop_observers_; +}; + +WorkerTaskRunner::WorkerTaskRunner() { + // Start worker ids at 1, 0 is reserved for the main thread. + int id = id_sequence_.GetNext(); + DCHECK(!id); +} + +void WorkerTaskRunner::PostTask( + int id, const base::Closure& closure) { + DCHECK(id > 0); + base::AutoLock locker(loop_map_lock_); + IDToLoopMap::iterator found = loop_map_.find(id); + if (found != loop_map_.end()) + found->second.postTask(new RunClosureTask(closure)); +} + +int WorkerTaskRunner::CurrentWorkerId() { + if (!current_tls_.Get()) + return 0; + return current_tls_.Get()->id_; +} + +WorkerTaskRunner* WorkerTaskRunner::Instance() { + static base::LazyInstance<WorkerTaskRunner, + base::LeakyLazyInstanceTraits<WorkerTaskRunner> > + worker_task_runner = LAZY_INSTANCE_INITIALIZER; + return worker_task_runner.Pointer(); +} + +void WorkerTaskRunner::AddStopObserver(Observer* obs) { + DCHECK(CurrentWorkerId() > 0); + current_tls_.Get()->stop_observers_.AddObserver(obs); +} + +void WorkerTaskRunner::RemoveStopObserver(Observer* obs) { + DCHECK(CurrentWorkerId() > 0); + current_tls_.Get()->stop_observers_.RemoveObserver(obs); +} + +WorkerTaskRunner::~WorkerTaskRunner() { +} + +void WorkerTaskRunner::OnWorkerRunLoopStarted(const WebWorkerRunLoop& loop) { + DCHECK(!current_tls_.Get()); + int id = id_sequence_.GetNext(); + current_tls_.Set(new ThreadLocalState(id, loop)); + + base::AutoLock locker_(loop_map_lock_); + loop_map_[id] = loop; +} + +void WorkerTaskRunner::OnWorkerRunLoopStopped(const WebWorkerRunLoop& loop) { + DCHECK(current_tls_.Get()); + FOR_EACH_OBSERVER(Observer, current_tls_.Get()->stop_observers_, + OnWorkerRunLoopStopped()); + { + base::AutoLock locker(loop_map_lock_); + DCHECK(loop_map_[CurrentWorkerId()] == loop); + loop_map_.erase(CurrentWorkerId()); + } + delete current_tls_.Get(); + current_tls_.Set(NULL); +} + +} // namespace webkit_glue diff --git a/webkit/glue/worker_task_runner.h b/webkit/glue/worker_task_runner.h new file mode 100644 index 0000000..6eea8c0 --- /dev/null +++ b/webkit/glue/worker_task_runner.h @@ -0,0 +1,59 @@ +// Copyright (c) 2011 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 WEBKIT_GLUE_WORKER_TASK_RUNNER_H_ +#define WEBKIT_GLUE_WORKER_TASK_RUNNER_H_ +#pragma once + +#include <map> + +#include "base/atomic_sequence_num.h" +#include "base/callback_forward.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_local.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerRunLoop.h" +#include "webkit/glue/webkit_glue_export.h" + +namespace webkit_glue { + +class WEBKIT_GLUE_EXPORT WorkerTaskRunner { + public: + WorkerTaskRunner(); + + void PostTask(int id, const base::Closure& task); + int CurrentWorkerId(); + static WorkerTaskRunner* Instance(); + + class Observer { + public: + virtual ~Observer() {} + virtual void OnWorkerRunLoopStopped() = 0; + }; + // Add/Remove an observer that will get notified when the current worker run + // loop is stopping. This observer will not get notified when other threads + // are stopping. It's only valid to call these on a worker thread. + void AddStopObserver(Observer* observer); + void RemoveStopObserver(Observer* observer); + + private: + friend class WebKitPlatformSupportImpl; + friend class WorkerTaskRunnerTest; + + typedef std::map<int, WebKit::WebWorkerRunLoop> IDToLoopMap; + + ~WorkerTaskRunner(); + void OnWorkerRunLoopStarted(const WebKit::WebWorkerRunLoop& loop); + void OnWorkerRunLoopStopped(const WebKit::WebWorkerRunLoop& loop); + + struct ThreadLocalState; + base::ThreadLocalPointer<ThreadLocalState> current_tls_; + + base::AtomicSequenceNumber id_sequence_; + IDToLoopMap loop_map_; + base::Lock loop_map_lock_; +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WORKER_TASK_RUNNER_H_ diff --git a/webkit/glue/worker_task_runner_unittest.cc b/webkit/glue/worker_task_runner_unittest.cc new file mode 100644 index 0000000..0ac4f2e --- /dev/null +++ b/webkit/glue/worker_task_runner_unittest.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2011 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 "base/logging.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/worker_task_runner.h" + +namespace webkit_glue { + +class WorkerTaskRunnerTest : public testing::Test { + public: + void FakeStart() { + task_runner_.OnWorkerRunLoopStarted(WebKit::WebWorkerRunLoop()); + } + void FakeStop() { + task_runner_.OnWorkerRunLoopStopped(WebKit::WebWorkerRunLoop()); + } + WorkerTaskRunner task_runner_; +}; + +class MockObserver : public WorkerTaskRunner::Observer { + public: + MOCK_METHOD0(OnWorkerRunLoopStopped, void()); + void RemoveSelfOnNotify() { + ON_CALL(*this, OnWorkerRunLoopStopped()).WillByDefault( + testing::Invoke(this, &MockObserver::RemoveSelf)); + } + void RemoveSelf() { + runner_->RemoveStopObserver(this); + } + WorkerTaskRunner* runner_; +}; + +TEST_F(WorkerTaskRunnerTest, BasicObservingAndWorkerId) { + ASSERT_EQ(0, task_runner_.CurrentWorkerId()); + MockObserver o; + EXPECT_CALL(o, OnWorkerRunLoopStopped()).Times(1); + FakeStart(); + task_runner_.AddStopObserver(&o); + ASSERT_LT(0, task_runner_.CurrentWorkerId()); + FakeStop(); +} + +TEST_F(WorkerTaskRunnerTest, CanRemoveSelfDuringNotification) { + MockObserver o; + o.RemoveSelfOnNotify(); + o.runner_ = &task_runner_; + EXPECT_CALL(o, OnWorkerRunLoopStopped()).Times(1); + FakeStart(); + task_runner_.AddStopObserver(&o); + FakeStop(); +} + +} diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi index 082c502..adfd6d3 100644 --- a/webkit/tools/test_shell/test_shell.gypi +++ b/webkit/tools/test_shell/test_shell.gypi @@ -429,6 +429,7 @@ '../../glue/webframe_unittest.cc', '../../glue/webkit_glue_unittest.cc', '../../glue/webview_unittest.cc', + '../../glue/worker_task_runner_unittest.cc', '../../media/buffered_data_source_unittest.cc', '../../media/buffered_resource_loader_unittest.cc', '../../media/simple_data_source_unittest.cc', |