1 // Copyright 2014 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 "content/child/worker_task_runner.h"
7 #include "base/callback.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/observer_list.h"
13 using blink::WebWorkerRunLoop
;
19 class RunClosureTask
: public WebWorkerRunLoop::Task
{
21 RunClosureTask(const base::Closure
& task
) : task_(task
) {}
22 virtual ~RunClosureTask() {}
32 struct WorkerTaskRunner::ThreadLocalState
{
33 ThreadLocalState(int id
, const WebWorkerRunLoop
& loop
)
34 : id_(id
), run_loop_(loop
) {
37 WebWorkerRunLoop run_loop_
;
38 ObserverList
<WorkerTaskRunner::Observer
> stop_observers_
;
41 WorkerTaskRunner::WorkerTaskRunner() {
42 // Start worker ids at 1, 0 is reserved for the main thread.
43 int id
= id_sequence_
.GetNext();
47 bool WorkerTaskRunner::PostTask(
48 int id
, const base::Closure
& closure
) {
50 base::AutoLock
locker(loop_map_lock_
);
51 IDToLoopMap::iterator found
= loop_map_
.find(id
);
52 if (found
== loop_map_
.end())
54 return found
->second
.postTask(new RunClosureTask(closure
));
57 int WorkerTaskRunner::PostTaskToAllThreads(const base::Closure
& closure
) {
58 base::AutoLock
locker(loop_map_lock_
);
59 IDToLoopMap::iterator it
;
60 for (it
= loop_map_
.begin(); it
!= loop_map_
.end(); ++it
)
61 it
->second
.postTask(new RunClosureTask(closure
));
62 return static_cast<int>(loop_map_
.size());
65 int WorkerTaskRunner::CurrentWorkerId() {
66 if (!current_tls_
.Get())
68 return current_tls_
.Get()->id_
;
71 WorkerTaskRunner
* WorkerTaskRunner::Instance() {
72 static base::LazyInstance
<WorkerTaskRunner
>::Leaky
73 worker_task_runner
= LAZY_INSTANCE_INITIALIZER
;
74 return worker_task_runner
.Pointer();
77 void WorkerTaskRunner::AddStopObserver(Observer
* obs
) {
78 DCHECK(CurrentWorkerId() > 0);
79 current_tls_
.Get()->stop_observers_
.AddObserver(obs
);
82 void WorkerTaskRunner::RemoveStopObserver(Observer
* obs
) {
83 DCHECK(CurrentWorkerId() > 0);
84 current_tls_
.Get()->stop_observers_
.RemoveObserver(obs
);
87 WorkerTaskRunner::~WorkerTaskRunner() {
90 void WorkerTaskRunner::OnWorkerRunLoopStarted(const WebWorkerRunLoop
& loop
) {
91 DCHECK(!current_tls_
.Get());
92 int id
= id_sequence_
.GetNext();
93 current_tls_
.Set(new ThreadLocalState(id
, loop
));
95 base::AutoLock
locker_(loop_map_lock_
);
99 void WorkerTaskRunner::OnWorkerRunLoopStopped(const WebWorkerRunLoop
& loop
) {
100 DCHECK(current_tls_
.Get());
101 FOR_EACH_OBSERVER(Observer
, current_tls_
.Get()->stop_observers_
,
102 OnWorkerRunLoopStopped());
104 base::AutoLock
locker(loop_map_lock_
);
105 DCHECK(loop_map_
[CurrentWorkerId()] == loop
);
106 loop_map_
.erase(CurrentWorkerId());
108 delete current_tls_
.Get();
109 current_tls_
.Set(NULL
);
112 } // namespace content