OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "ios/web/web_thread_impl.h" | 5 #include "ios/web/web_thread_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 } | 42 } |
43 | 43 |
44 // An implementation of SingleThreadTaskRunner to be used in conjunction | 44 // An implementation of SingleThreadTaskRunner to be used in conjunction |
45 // with WebThread. | 45 // with WebThread. |
46 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { | 46 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { |
47 public: | 47 public: |
48 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} | 48 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} |
49 | 49 |
50 // SingleThreadTaskRunner implementation. | 50 // SingleThreadTaskRunner implementation. |
51 bool PostDelayedTask(const tracked_objects::Location& from_here, | 51 bool PostDelayedTask(const tracked_objects::Location& from_here, |
52 const base::Closure& task, | 52 base::Closure task, |
53 base::TimeDelta delay) override { | 53 base::TimeDelta delay) override { |
54 return WebThread::PostDelayedTask(id_, from_here, task, delay); | 54 return WebThread::PostDelayedTask(id_, from_here, std::move(task), delay); |
55 } | 55 } |
56 | 56 |
57 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 57 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
58 const base::Closure& task, | 58 base::Closure task, |
59 base::TimeDelta delay) override { | 59 base::TimeDelta delay) override { |
60 return WebThread::PostNonNestableDelayedTask(id_, from_here, task, delay); | 60 return WebThread::PostNonNestableDelayedTask(id_, from_here, |
| 61 std::move(task), delay); |
61 } | 62 } |
62 | 63 |
63 bool RunsTasksOnCurrentThread() const override { | 64 bool RunsTasksOnCurrentThread() const override { |
64 return WebThread::CurrentlyOn(id_); | 65 return WebThread::CurrentlyOn(id_); |
65 } | 66 } |
66 | 67 |
67 protected: | 68 protected: |
68 ~WebThreadTaskRunner() override {} | 69 ~WebThreadTaskRunner() override {} |
69 | 70 |
70 private: | 71 private: |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { | 284 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { |
284 DCHECK(!globals.threads[i]) | 285 DCHECK(!globals.threads[i]) |
285 << "Threads must be listed in the reverse order that they die"; | 286 << "Threads must be listed in the reverse order that they die"; |
286 } | 287 } |
287 #endif | 288 #endif |
288 } | 289 } |
289 | 290 |
290 // static | 291 // static |
291 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, | 292 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, |
292 const tracked_objects::Location& from_here, | 293 const tracked_objects::Location& from_here, |
293 const base::Closure& task, | 294 base::Closure task, |
294 base::TimeDelta delay, | 295 base::TimeDelta delay, |
295 bool nestable) { | 296 bool nestable) { |
296 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 297 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
297 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in | 298 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in |
298 // order of lifetime. So no need to lock if we know that the target thread | 299 // order of lifetime. So no need to lock if we know that the target thread |
299 // outlives current thread. | 300 // outlives current thread. |
300 // Note: since the array is so small, ok to loop instead of creating a map, | 301 // Note: since the array is so small, ok to loop instead of creating a map, |
301 // which would require a lock because std::map isn't thread safe, defeating | 302 // which would require a lock because std::map isn't thread safe, defeating |
302 // the whole purpose of this optimization. | 303 // the whole purpose of this optimization. |
303 WebThread::ID current_thread = ID_COUNT; | 304 WebThread::ID current_thread = ID_COUNT; |
304 bool target_thread_outlives_current = | 305 bool target_thread_outlives_current = |
305 GetCurrentThreadIdentifier(¤t_thread) && | 306 GetCurrentThreadIdentifier(¤t_thread) && |
306 current_thread >= identifier; | 307 current_thread >= identifier; |
307 | 308 |
308 WebThreadGlobals& globals = g_globals.Get(); | 309 WebThreadGlobals& globals = g_globals.Get(); |
309 if (!target_thread_outlives_current) | 310 if (!target_thread_outlives_current) |
310 globals.lock.Acquire(); | 311 globals.lock.Acquire(); |
311 | 312 |
312 base::MessageLoop* message_loop = | 313 base::MessageLoop* message_loop = |
313 globals.threads[identifier] ? globals.threads[identifier]->message_loop() | 314 globals.threads[identifier] ? globals.threads[identifier]->message_loop() |
314 : nullptr; | 315 : nullptr; |
315 if (message_loop) { | 316 if (message_loop) { |
316 if (nestable) { | 317 if (nestable) { |
317 message_loop->task_runner()->PostDelayedTask(from_here, task, delay); | 318 message_loop->task_runner()->PostDelayedTask(from_here, std::move(task), |
| 319 delay); |
318 } else { | 320 } else { |
319 message_loop->task_runner()->PostNonNestableDelayedTask(from_here, task, | 321 message_loop->task_runner()->PostNonNestableDelayedTask( |
320 delay); | 322 from_here, std::move(task), delay); |
321 } | 323 } |
322 } | 324 } |
323 | 325 |
324 if (!target_thread_outlives_current) | 326 if (!target_thread_outlives_current) |
325 globals.lock.Release(); | 327 globals.lock.Release(); |
326 | 328 |
327 return !!message_loop; | 329 return !!message_loop; |
328 } | 330 } |
329 | 331 |
330 // static | 332 // static |
331 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, | 333 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, |
332 const base::Closure& task) { | 334 base::Closure task) { |
333 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task); | 335 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, |
| 336 std::move(task)); |
334 } | 337 } |
335 | 338 |
336 // static | 339 // static |
337 bool WebThread::PostBlockingPoolTaskAndReply( | 340 bool WebThread::PostBlockingPoolTaskAndReply( |
338 const tracked_objects::Location& from_here, | 341 const tracked_objects::Location& from_here, |
339 base::Closure task, | 342 base::Closure task, |
340 base::Closure reply) { | 343 base::Closure reply) { |
341 return g_globals.Get().blocking_pool->PostTaskAndReply( | 344 return g_globals.Get().blocking_pool->PostTaskAndReply( |
342 from_here, std::move(task), std::move(reply)); | 345 from_here, std::move(task), std::move(reply)); |
343 } | 346 } |
344 | 347 |
345 // static | 348 // static |
346 bool WebThread::PostBlockingPoolSequencedTask( | 349 bool WebThread::PostBlockingPoolSequencedTask( |
347 const std::string& sequence_token_name, | 350 const std::string& sequence_token_name, |
348 const tracked_objects::Location& from_here, | 351 const tracked_objects::Location& from_here, |
349 const base::Closure& task) { | 352 base::Closure task) { |
350 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( | 353 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( |
351 sequence_token_name, from_here, task); | 354 sequence_token_name, from_here, std::move(task)); |
352 } | 355 } |
353 | 356 |
354 // static | 357 // static |
355 base::SequencedWorkerPool* WebThread::GetBlockingPool() { | 358 base::SequencedWorkerPool* WebThread::GetBlockingPool() { |
356 return g_globals.Get().blocking_pool.get(); | 359 return g_globals.Get().blocking_pool.get(); |
357 } | 360 } |
358 | 361 |
359 // static | 362 // static |
360 bool WebThread::IsThreadInitialized(ID identifier) { | 363 bool WebThread::IsThreadInitialized(ID identifier) { |
361 if (g_globals == nullptr) | 364 if (g_globals == nullptr) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 WebThreadGlobals& globals = g_globals.Get(); | 402 WebThreadGlobals& globals = g_globals.Get(); |
400 base::AutoLock lock(globals.lock); | 403 base::AutoLock lock(globals.lock); |
401 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 404 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
402 return globals.threads[identifier] && | 405 return globals.threads[identifier] && |
403 globals.threads[identifier]->message_loop(); | 406 globals.threads[identifier]->message_loop(); |
404 } | 407 } |
405 | 408 |
406 // static | 409 // static |
407 bool WebThread::PostTask(ID identifier, | 410 bool WebThread::PostTask(ID identifier, |
408 const tracked_objects::Location& from_here, | 411 const tracked_objects::Location& from_here, |
409 const base::Closure& task) { | 412 base::Closure task) { |
410 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 413 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
411 base::TimeDelta(), true); | 414 base::TimeDelta(), true); |
412 } | 415 } |
413 | 416 |
414 // static | 417 // static |
415 bool WebThread::PostDelayedTask(ID identifier, | 418 bool WebThread::PostDelayedTask(ID identifier, |
416 const tracked_objects::Location& from_here, | 419 const tracked_objects::Location& from_here, |
417 const base::Closure& task, | 420 base::Closure task, |
418 base::TimeDelta delay) { | 421 base::TimeDelta delay) { |
419 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 422 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
420 true); | 423 delay, true); |
421 } | 424 } |
422 | 425 |
423 // static | 426 // static |
424 bool WebThread::PostNonNestableTask(ID identifier, | 427 bool WebThread::PostNonNestableTask(ID identifier, |
425 const tracked_objects::Location& from_here, | 428 const tracked_objects::Location& from_here, |
426 const base::Closure& task) { | 429 base::Closure task) { |
427 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 430 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
428 base::TimeDelta(), false); | 431 base::TimeDelta(), false); |
429 } | 432 } |
430 | 433 |
431 // static | 434 // static |
432 bool WebThread::PostNonNestableDelayedTask( | 435 bool WebThread::PostNonNestableDelayedTask( |
433 ID identifier, | 436 ID identifier, |
434 const tracked_objects::Location& from_here, | 437 const tracked_objects::Location& from_here, |
435 const base::Closure& task, | 438 base::Closure task, |
436 base::TimeDelta delay) { | 439 base::TimeDelta delay) { |
437 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 440 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
438 false); | 441 delay, false); |
439 } | 442 } |
440 | 443 |
441 // static | 444 // static |
442 bool WebThread::PostTaskAndReply(ID identifier, | 445 bool WebThread::PostTaskAndReply(ID identifier, |
443 const tracked_objects::Location& from_here, | 446 const tracked_objects::Location& from_here, |
444 base::Closure task, | 447 base::Closure task, |
445 base::Closure reply) { | 448 base::Closure reply) { |
446 return GetTaskRunnerForThread(identifier) | 449 return GetTaskRunnerForThread(identifier) |
447 ->PostTaskAndReply(from_here, std::move(task), std::move(reply)); | 450 ->PostTaskAndReply(from_here, std::move(task), std::move(reply)); |
448 } | 451 } |
(...skipping 29 matching lines...) Expand all Loading... |
478 AtomicWord* storage = | 481 AtomicWord* storage = |
479 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); | 482 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); |
480 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 483 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
481 storage, reinterpret_cast<AtomicWord>(delegate)); | 484 storage, reinterpret_cast<AtomicWord>(delegate)); |
482 | 485 |
483 // This catches registration when previously registered. | 486 // This catches registration when previously registered. |
484 DCHECK(!delegate || !old_pointer); | 487 DCHECK(!delegate || !old_pointer); |
485 } | 488 } |
486 | 489 |
487 } // namespace web | 490 } // namespace web |
OLD | NEW |