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