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.
4
5 // An implementation of WebThread in terms of base::MessageLoop and
6 // base::Thread
7
8 #include "mojo/examples/html_viewer/webthread_impl.h"
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/pending_task.h"
14 #include "base/threading/platform_thread.h"
15
16 namespace mojo {
17 namespace examples {
18
WebThreadBase()19 WebThreadBase::WebThreadBase() {}
~WebThreadBase()20 WebThreadBase::~WebThreadBase() {}
21
22 class WebThreadBase::TaskObserverAdapter
23 : public base::MessageLoop::TaskObserver {
24 public:
TaskObserverAdapter(WebThread::TaskObserver * observer)25 TaskObserverAdapter(WebThread::TaskObserver* observer)
26 : observer_(observer) {}
27
WillProcessTask(const base::PendingTask & pending_task)28 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
29 observer_->willProcessTask();
30 }
31
DidProcessTask(const base::PendingTask & pending_task)32 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
33 observer_->didProcessTask();
34 }
35
36 private:
37 WebThread::TaskObserver* observer_;
38 };
39
addTaskObserver(TaskObserver * observer)40 void WebThreadBase::addTaskObserver(TaskObserver* observer) {
41 CHECK(isCurrentThread());
42 std::pair<TaskObserverMap::iterator, bool> result = task_observer_map_.insert(
43 std::make_pair(observer, static_cast<TaskObserverAdapter*>(NULL)));
44 if (result.second)
45 result.first->second = new TaskObserverAdapter(observer);
46 base::MessageLoop::current()->AddTaskObserver(result.first->second);
47 }
48
removeTaskObserver(TaskObserver * observer)49 void WebThreadBase::removeTaskObserver(TaskObserver* observer) {
50 CHECK(isCurrentThread());
51 TaskObserverMap::iterator iter = task_observer_map_.find(observer);
52 if (iter == task_observer_map_.end())
53 return;
54 base::MessageLoop::current()->RemoveTaskObserver(iter->second);
55 delete iter->second;
56 task_observer_map_.erase(iter);
57 }
58
WebThreadImpl(const char * name)59 WebThreadImpl::WebThreadImpl(const char* name)
60 : thread_(new base::Thread(name)) {
61 thread_->Start();
62 }
63
postTask(Task * task)64 void WebThreadImpl::postTask(Task* task) {
65 thread_->message_loop()->PostTask(
66 FROM_HERE, base::Bind(&blink::WebThread::Task::run, base::Owned(task)));
67 }
68
postDelayedTask(Task * task,long long delay_ms)69 void WebThreadImpl::postDelayedTask(Task* task, long long delay_ms) {
70 thread_->message_loop()->PostDelayedTask(
71 FROM_HERE,
72 base::Bind(&blink::WebThread::Task::run, base::Owned(task)),
73 base::TimeDelta::FromMilliseconds(delay_ms));
74 }
75
enterRunLoop()76 void WebThreadImpl::enterRunLoop() {
77 CHECK(isCurrentThread());
78 CHECK(!thread_->message_loop()->is_running()); // We don't support nesting.
79 thread_->message_loop()->Run();
80 }
81
exitRunLoop()82 void WebThreadImpl::exitRunLoop() {
83 CHECK(isCurrentThread());
84 CHECK(thread_->message_loop()->is_running());
85 thread_->message_loop()->Quit();
86 }
87
isCurrentThread() const88 bool WebThreadImpl::isCurrentThread() const {
89 return thread_->thread_id() == base::PlatformThread::CurrentId();
90 }
91
~WebThreadImpl()92 WebThreadImpl::~WebThreadImpl() {
93 thread_->Stop();
94 }
95
WebThreadImplForMessageLoop(base::MessageLoopProxy * message_loop)96 WebThreadImplForMessageLoop::WebThreadImplForMessageLoop(
97 base::MessageLoopProxy* message_loop)
98 : message_loop_(message_loop) {}
99
postTask(Task * task)100 void WebThreadImplForMessageLoop::postTask(Task* task) {
101 message_loop_->PostTask(
102 FROM_HERE, base::Bind(&blink::WebThread::Task::run, base::Owned(task)));
103 }
104
postDelayedTask(Task * task,long long delay_ms)105 void WebThreadImplForMessageLoop::postDelayedTask(Task* task,
106 long long delay_ms) {
107 message_loop_->PostDelayedTask(
108 FROM_HERE,
109 base::Bind(&blink::WebThread::Task::run, base::Owned(task)),
110 base::TimeDelta::FromMilliseconds(delay_ms));
111 }
112
enterRunLoop()113 void WebThreadImplForMessageLoop::enterRunLoop() {
114 CHECK(isCurrentThread());
115 // We don't support nesting.
116 CHECK(!base::MessageLoop::current()->is_running());
117 base::MessageLoop::current()->Run();
118 }
119
exitRunLoop()120 void WebThreadImplForMessageLoop::exitRunLoop() {
121 CHECK(isCurrentThread());
122 CHECK(base::MessageLoop::current()->is_running());
123 base::MessageLoop::current()->Quit();
124 }
125
isCurrentThread() const126 bool WebThreadImplForMessageLoop::isCurrentThread() const {
127 return message_loop_->BelongsToCurrentThread();
128 }
129
~WebThreadImplForMessageLoop()130 WebThreadImplForMessageLoop::~WebThreadImplForMessageLoop() {}
131
132 } // namespace examples
133 } // namespace mojo
134