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/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/observer_list.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h"
15 #include "base/thread_task_runner_handle.h"
21 // A task-runner that refuses to run any tasks.
22 class DoNothingTaskRunner
: public base::TaskRunner
{
24 DoNothingTaskRunner() {}
27 ~DoNothingTaskRunner() override
{}
29 bool PostDelayedTask(const tracked_objects::Location
& from_here
,
30 const base::Closure
& task
,
31 base::TimeDelta delay
) override
{
35 bool RunsTasksOnCurrentThread() const override
{ return false; }
40 struct WorkerTaskRunner::ThreadLocalState
{
42 base::ObserverList
<WorkerTaskRunner::Observer
> stop_observers_
;
45 WorkerTaskRunner::WorkerTaskRunner()
46 : task_runner_for_dead_worker_(new DoNothingTaskRunner()) {
49 bool WorkerTaskRunner::PostTask(
50 int id
, const base::Closure
& closure
) {
52 base::AutoLock
locker(task_runner_map_lock_
);
53 IDToTaskRunnerMap::iterator found
= task_runner_map_
.find(id
);
54 if (found
== task_runner_map_
.end())
56 return found
->second
->PostTask(FROM_HERE
, closure
);
59 int WorkerTaskRunner::PostTaskToAllThreads(const base::Closure
& closure
) {
60 base::AutoLock
locker(task_runner_map_lock_
);
61 for (const auto& it
: task_runner_map_
)
62 it
.second
->PostTask(FROM_HERE
, closure
);
63 return static_cast<int>(task_runner_map_
.size());
66 int WorkerTaskRunner::CurrentWorkerId() {
67 if (!current_tls_
.Get())
69 return base::PlatformThread::CurrentId();
72 WorkerTaskRunner
* WorkerTaskRunner::Instance() {
73 static base::LazyInstance
<WorkerTaskRunner
>::Leaky
74 worker_task_runner
= LAZY_INSTANCE_INITIALIZER
;
75 return worker_task_runner
.Pointer();
78 void WorkerTaskRunner::AddStopObserver(Observer
* obs
) {
79 DCHECK(CurrentWorkerId() > 0);
80 current_tls_
.Get()->stop_observers_
.AddObserver(obs
);
83 void WorkerTaskRunner::RemoveStopObserver(Observer
* obs
) {
84 DCHECK(CurrentWorkerId() > 0);
85 current_tls_
.Get()->stop_observers_
.RemoveObserver(obs
);
88 WorkerTaskRunner::~WorkerTaskRunner() {
91 void WorkerTaskRunner::OnWorkerRunLoopStarted() {
92 DCHECK(!current_tls_
.Get());
93 DCHECK(!base::PlatformThread::CurrentRef().is_null());
94 current_tls_
.Set(new ThreadLocalState());
96 int id
= base::PlatformThread::CurrentId();
97 base::AutoLock
locker_(task_runner_map_lock_
);
98 task_runner_map_
[id
] = base::ThreadTaskRunnerHandle::Get().get();
99 CHECK(task_runner_map_
[id
]);
102 void WorkerTaskRunner::OnWorkerRunLoopStopped() {
103 DCHECK(current_tls_
.Get());
104 FOR_EACH_OBSERVER(Observer
, current_tls_
.Get()->stop_observers_
,
105 OnWorkerRunLoopStopped());
107 base::AutoLock
locker(task_runner_map_lock_
);
108 task_runner_map_
.erase(CurrentWorkerId());
110 delete current_tls_
.Get();
111 current_tls_
.Set(NULL
);
114 base::TaskRunner
* WorkerTaskRunner::GetTaskRunnerFor(int worker_id
) {
115 base::AutoLock
locker(task_runner_map_lock_
);
116 return ContainsKey(task_runner_map_
, worker_id
) ? task_runner_map_
[worker_id
]
117 : task_runner_for_dead_worker_
.get();
120 } // namespace content