1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/callback.h"
6 #include "base/lazy_instance.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/observer_list.h"
10 #include "webkit/child/worker_task_runner.h"
12 using blink::WebWorkerRunLoop
;
16 class RunClosureTask
: public WebWorkerRunLoop::Task
{
18 RunClosureTask(const base::Closure
& task
) : task_(task
) {}
19 virtual ~RunClosureTask() {}
27 } // unnamed namespace
29 namespace webkit_glue
{
31 struct WorkerTaskRunner::ThreadLocalState
{
32 ThreadLocalState(int id
, const WebWorkerRunLoop
& loop
)
33 : id_(id
), run_loop_(loop
) {
36 WebWorkerRunLoop run_loop_
;
37 ObserverList
<WorkerTaskRunner::Observer
> stop_observers_
;
40 WorkerTaskRunner::WorkerTaskRunner() {
41 // Start worker ids at 1, 0 is reserved for the main thread.
42 int id
= id_sequence_
.GetNext();
46 bool WorkerTaskRunner::PostTask(
47 int id
, const base::Closure
& closure
) {
49 base::AutoLock
locker(loop_map_lock_
);
50 IDToLoopMap::iterator found
= loop_map_
.find(id
);
51 if (found
== loop_map_
.end())
53 return found
->second
.postTask(new RunClosureTask(closure
));
56 int WorkerTaskRunner::PostTaskToAllThreads(const base::Closure
& closure
) {
57 base::AutoLock
locker(loop_map_lock_
);
58 IDToLoopMap::iterator it
;
59 for (it
= loop_map_
.begin(); it
!= loop_map_
.end(); ++it
)
60 it
->second
.postTask(new RunClosureTask(closure
));
61 return static_cast<int>(loop_map_
.size());
64 int WorkerTaskRunner::CurrentWorkerId() {
65 if (!current_tls_
.Get())
67 return current_tls_
.Get()->id_
;
70 WorkerTaskRunner
* WorkerTaskRunner::Instance() {
71 static base::LazyInstance
<WorkerTaskRunner
>::Leaky
72 worker_task_runner
= LAZY_INSTANCE_INITIALIZER
;
73 return worker_task_runner
.Pointer();
76 void WorkerTaskRunner::AddStopObserver(Observer
* obs
) {
77 DCHECK(CurrentWorkerId() > 0);
78 current_tls_
.Get()->stop_observers_
.AddObserver(obs
);
81 void WorkerTaskRunner::RemoveStopObserver(Observer
* obs
) {
82 DCHECK(CurrentWorkerId() > 0);
83 current_tls_
.Get()->stop_observers_
.RemoveObserver(obs
);
86 WorkerTaskRunner::~WorkerTaskRunner() {
89 void WorkerTaskRunner::OnWorkerRunLoopStarted(const WebWorkerRunLoop
& loop
) {
90 DCHECK(!current_tls_
.Get());
91 int id
= id_sequence_
.GetNext();
92 current_tls_
.Set(new ThreadLocalState(id
, loop
));
94 base::AutoLock
locker_(loop_map_lock_
);
98 void WorkerTaskRunner::OnWorkerRunLoopStopped(const WebWorkerRunLoop
& loop
) {
99 DCHECK(current_tls_
.Get());
100 FOR_EACH_OBSERVER(Observer
, current_tls_
.Get()->stop_observers_
,
101 OnWorkerRunLoopStopped());
103 base::AutoLock
locker(loop_map_lock_
);
104 DCHECK(loop_map_
[CurrentWorkerId()] == loop
);
105 loop_map_
.erase(CurrentWorkerId());
107 delete current_tls_
.Get();
108 current_tls_
.Set(NULL
);
111 } // namespace webkit_glue