Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / worker_task_runner.cc
blobbd469c1fbe52270ba72ba878987c08066f0baee8
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"
17 namespace content {
19 namespace {
21 // A task-runner that refuses to run any tasks.
22 class DoNothingTaskRunner : public base::TaskRunner {
23 public:
24 DoNothingTaskRunner() {}
26 private:
27 ~DoNothingTaskRunner() override {}
29 bool PostDelayedTask(const tracked_objects::Location& from_here,
30 const base::Closure& task,
31 base::TimeDelta delay) override {
32 return false;
35 bool RunsTasksOnCurrentThread() const override { return false; }
38 } // namespace
40 struct WorkerTaskRunner::ThreadLocalState {
41 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) {
51 DCHECK(id > 0);
52 base::AutoLock locker(task_runner_map_lock_);
53 IDToTaskRunnerMap::iterator found = task_runner_map_.find(id);
54 if (found == task_runner_map_.end())
55 return false;
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())
68 return 0;
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