Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: content/browser/browser_thread.cc

Issue 8340028: Salient parts of http://codereview.chromium.org/8392042/ (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/browser_thread.h ('k') | content/browser/browser_thread_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #include "content/browser/browser_thread.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop.h"
9 #include "base/message_loop_proxy.h"
10 #include "base/threading/thread_restrictions.h"
11
12 // Friendly names for the well-known threads.
13 static const char* browser_thread_names[BrowserThread::ID_COUNT] = {
14 "", // UI (name assembled in browser_main.cc).
15 "Chrome_DBThread", // DB
16 "Chrome_WebKitThread", // WEBKIT
17 "Chrome_FileThread", // FILE
18 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER
19 "Chrome_CacheThread", // CACHE
20 "Chrome_IOThread", // IO
21 #if defined(OS_CHROMEOS)
22 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY
23 #endif
24 };
25
26 // An implementation of MessageLoopProxy to be used in conjunction
27 // with BrowserThread.
28 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
29 public:
30 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
31 : id_(identifier) {
32 }
33
34 // MessageLoopProxy implementation.
35 virtual bool PostTask(const tracked_objects::Location& from_here,
36 Task* task) {
37 return BrowserThread::PostTask(id_, from_here, task);
38 }
39
40 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
41 Task* task, int64 delay_ms) {
42 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms);
43 }
44
45 virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
46 Task* task) {
47 return BrowserThread::PostNonNestableTask(id_, from_here, task);
48 }
49
50 virtual bool PostNonNestableDelayedTask(
51 const tracked_objects::Location& from_here,
52 Task* task,
53 int64 delay_ms) {
54 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
55 delay_ms);
56 }
57
58 virtual bool PostTask(const tracked_objects::Location& from_here,
59 const base::Closure& task) {
60 return BrowserThread::PostTask(id_, from_here, task);
61 }
62
63 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
64 const base::Closure& task, int64 delay_ms) {
65 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms);
66 }
67
68 virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
69 const base::Closure& task) {
70 return BrowserThread::PostNonNestableTask(id_, from_here, task);
71 }
72
73 virtual bool PostNonNestableDelayedTask(
74 const tracked_objects::Location& from_here,
75 const base::Closure& task,
76 int64 delay_ms) {
77 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
78 delay_ms);
79 }
80
81 virtual bool BelongsToCurrentThread() {
82 return BrowserThread::CurrentlyOn(id_);
83 }
84
85 private:
86 BrowserThread::ID id_;
87 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
88 };
89
90
91 base::Lock BrowserThread::lock_;
92
93 BrowserThread* BrowserThread::browser_threads_[ID_COUNT];
94
95 BrowserThread::BrowserThread(BrowserThread::ID identifier)
96 : Thread(browser_thread_names[identifier]),
97 identifier_(identifier) {
98 Initialize();
99 }
100
101 BrowserThread::BrowserThread(ID identifier, MessageLoop* message_loop)
102 : Thread(message_loop->thread_name().c_str()),
103 identifier_(identifier) {
104 set_message_loop(message_loop);
105 Initialize();
106 }
107
108 void BrowserThread::Initialize() {
109 base::AutoLock lock(lock_);
110 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
111 DCHECK(browser_threads_[identifier_] == NULL);
112 browser_threads_[identifier_] = this;
113 }
114
115 BrowserThread::~BrowserThread() {
116 // Stop the thread here, instead of the parent's class destructor. This is so
117 // that if there are pending tasks that run, code that checks that it's on the
118 // correct BrowserThread succeeds.
119 Stop();
120
121 base::AutoLock lock(lock_);
122 browser_threads_[identifier_] = NULL;
123 #ifndef NDEBUG
124 // Double check that the threads are ordered correctly in the enumeration.
125 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
126 DCHECK(!browser_threads_[i]) <<
127 "Threads must be listed in the reverse order that they die";
128 }
129 #endif
130 }
131
132 // static
133 bool BrowserThread::IsWellKnownThread(ID identifier) {
134 base::AutoLock lock(lock_);
135 return (identifier >= 0 && identifier < ID_COUNT &&
136 browser_threads_[identifier]);
137 }
138
139 // static
140 bool BrowserThread::CurrentlyOn(ID identifier) {
141 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
142 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
143 // function.
144 // http://crbug.com/63678
145 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
146 base::AutoLock lock(lock_);
147 DCHECK(identifier >= 0 && identifier < ID_COUNT);
148 return browser_threads_[identifier] &&
149 browser_threads_[identifier]->message_loop() == MessageLoop::current();
150 }
151
152 // static
153 bool BrowserThread::IsMessageLoopValid(ID identifier) {
154 base::AutoLock lock(lock_);
155 DCHECK(identifier >= 0 && identifier < ID_COUNT);
156 return browser_threads_[identifier] &&
157 browser_threads_[identifier]->message_loop();
158 }
159
160 // static
161 bool BrowserThread::PostTask(ID identifier,
162 const tracked_objects::Location& from_here,
163 const base::Closure& task) {
164 return PostTaskHelper(identifier, from_here, task, 0, true);
165 }
166
167 // static
168 bool BrowserThread::PostDelayedTask(ID identifier,
169 const tracked_objects::Location& from_here,
170 const base::Closure& task,
171 int64 delay_ms) {
172 return PostTaskHelper(identifier, from_here, task, delay_ms, true);
173 }
174
175 // static
176 bool BrowserThread::PostNonNestableTask(
177 ID identifier,
178 const tracked_objects::Location& from_here,
179 const base::Closure& task) {
180 return PostTaskHelper(identifier, from_here, task, 0, false);
181 }
182
183 // static
184 bool BrowserThread::PostNonNestableDelayedTask(
185 ID identifier,
186 const tracked_objects::Location& from_here,
187 const base::Closure& task,
188 int64 delay_ms) {
189 return PostTaskHelper(identifier, from_here, task, delay_ms, false);
190 }
191
192 // static
193 bool BrowserThread::PostTask(ID identifier,
194 const tracked_objects::Location& from_here,
195 Task* task) {
196 return PostTaskHelper(identifier, from_here, task, 0, true);
197 }
198
199 // static
200 bool BrowserThread::PostDelayedTask(ID identifier,
201 const tracked_objects::Location& from_here,
202 Task* task,
203 int64 delay_ms) {
204 return PostTaskHelper(identifier, from_here, task, delay_ms, true);
205 }
206
207 // static
208 bool BrowserThread::PostNonNestableTask(
209 ID identifier,
210 const tracked_objects::Location& from_here,
211 Task* task) {
212 return PostTaskHelper(identifier, from_here, task, 0, false);
213 }
214
215 // static
216 bool BrowserThread::PostNonNestableDelayedTask(
217 ID identifier,
218 const tracked_objects::Location& from_here,
219 Task* task,
220 int64 delay_ms) {
221 return PostTaskHelper(identifier, from_here, task, delay_ms, false);
222 }
223
224 // static
225 bool BrowserThread::PostTaskAndReply(
226 ID identifier,
227 const tracked_objects::Location& from_here,
228 const base::Closure& task,
229 const base::Closure& reply) {
230 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here,
231 task,
232 reply);
233 }
234
235 // static
236 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
237 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
238 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
239 // function.
240 // http://crbug.com/63678
241 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
242 MessageLoop* cur_message_loop = MessageLoop::current();
243 for (int i = 0; i < ID_COUNT; ++i) {
244 if (browser_threads_[i] &&
245 browser_threads_[i]->message_loop() == cur_message_loop) {
246 *identifier = browser_threads_[i]->identifier_;
247 return true;
248 }
249 }
250
251 return false;
252 }
253
254 // static
255 scoped_refptr<base::MessageLoopProxy>
256 BrowserThread::GetMessageLoopProxyForThread(
257 ID identifier) {
258 scoped_refptr<base::MessageLoopProxy> proxy(
259 new BrowserThreadMessageLoopProxy(identifier));
260 return proxy;
261 }
262
263 // static
264 bool BrowserThread::PostTaskHelper(
265 ID identifier,
266 const tracked_objects::Location& from_here,
267 Task* task,
268 int64 delay_ms,
269 bool nestable) {
270 DCHECK(identifier >= 0 && identifier < ID_COUNT);
271 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
272 // order of lifetime. So no need to lock if we know that the other thread
273 // outlives this one.
274 // Note: since the array is so small, ok to loop instead of creating a map,
275 // which would require a lock because std::map isn't thread safe, defeating
276 // the whole purpose of this optimization.
277 ID current_thread;
278 bool guaranteed_to_outlive_target_thread =
279 GetCurrentThreadIdentifier(&current_thread) &&
280 current_thread >= identifier;
281
282 if (!guaranteed_to_outlive_target_thread)
283 lock_.Acquire();
284
285 MessageLoop* message_loop = browser_threads_[identifier] ?
286 browser_threads_[identifier]->message_loop() : NULL;
287 if (message_loop) {
288 if (nestable) {
289 message_loop->PostDelayedTask(from_here, task, delay_ms);
290 } else {
291 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
292 }
293 }
294
295 if (!guaranteed_to_outlive_target_thread)
296 lock_.Release();
297
298 if (!message_loop)
299 delete task;
300
301 return !!message_loop;
302 }
303
304 // static
305 bool BrowserThread::PostTaskHelper(
306 ID identifier,
307 const tracked_objects::Location& from_here,
308 const base::Closure& task,
309 int64 delay_ms,
310 bool nestable) {
311 DCHECK(identifier >= 0 && identifier < ID_COUNT);
312 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
313 // order of lifetime. So no need to lock if we know that the other thread
314 // outlives this one.
315 // Note: since the array is so small, ok to loop instead of creating a map,
316 // which would require a lock because std::map isn't thread safe, defeating
317 // the whole purpose of this optimization.
318 ID current_thread;
319 bool guaranteed_to_outlive_target_thread =
320 GetCurrentThreadIdentifier(&current_thread) &&
321 current_thread >= identifier;
322
323 if (!guaranteed_to_outlive_target_thread)
324 lock_.Acquire();
325
326 MessageLoop* message_loop = browser_threads_[identifier] ?
327 browser_threads_[identifier]->message_loop() : NULL;
328 if (message_loop) {
329 if (nestable) {
330 message_loop->PostDelayedTask(from_here, task, delay_ms);
331 } else {
332 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
333 }
334 }
335
336 if (!guaranteed_to_outlive_target_thread)
337 lock_.Release();
338
339 return !!message_loop;
340 }
OLDNEW
« no previous file with comments | « content/browser/browser_thread.h ('k') | content/browser/browser_thread_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698