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 | 8 |
9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
14 #include "base/single_thread_task_runner.h" | 14 #include "base/message_loop/message_loop_proxy.h" |
15 #include "base/threading/sequenced_worker_pool.h" | 15 #include "base/threading/sequenced_worker_pool.h" |
16 #include "base/threading/thread_restrictions.h" | 16 #include "base/threading/thread_restrictions.h" |
17 #include "ios/web/public/web_thread_delegate.h" | 17 #include "ios/web/public/web_thread_delegate.h" |
18 #include "net/disk_cache/simple/simple_backend_impl.h" | 18 #include "net/disk_cache/simple/simple_backend_impl.h" |
19 #include "net/url_request/url_fetcher.h" | 19 #include "net/url_request/url_fetcher.h" |
20 | 20 |
21 namespace web { | 21 namespace web { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 // Friendly names for the well-known threads. | 25 // Friendly names for the well-known threads. |
26 const char* g_web_thread_names[WebThread::ID_COUNT] = { | 26 const char* g_web_thread_names[WebThread::ID_COUNT] = { |
27 "Web_UIThread", // UI | 27 "Web_UIThread", // UI |
28 "Web_DBThread", // DB | 28 "Web_DBThread", // DB |
29 "Web_FileThread", // FILE | 29 "Web_FileThread", // FILE |
30 "Web_FileUserBlockingThread", // FILE_USER_BLOCKING | 30 "Web_FileUserBlockingThread", // FILE_USER_BLOCKING |
31 "Web_CacheThread", // CACHE | 31 "Web_CacheThread", // CACHE |
32 "Web_IOThread", // IO | 32 "Web_IOThread", // IO |
33 }; | 33 }; |
34 | 34 |
35 // An implementation of SingleThreadTaskRunner to be used in conjunction | 35 // An implementation of MessageLoopProxy to be used in conjunction |
36 // with WebThread. | 36 // with WebThread. |
37 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { | 37 class WebThreadMessageLoopProxy : public base::MessageLoopProxy { |
38 public: | 38 public: |
39 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} | 39 explicit WebThreadMessageLoopProxy(WebThread::ID identifier) |
| 40 : id_(identifier) {} |
40 | 41 |
41 // SingleThreadTaskRunner implementation. | 42 // MessageLoopProxy implementation. |
42 bool PostDelayedTask(const tracked_objects::Location& from_here, | 43 bool PostDelayedTask(const tracked_objects::Location& from_here, |
43 const base::Closure& task, | 44 const base::Closure& task, |
44 base::TimeDelta delay) override { | 45 base::TimeDelta delay) override { |
45 return WebThread::PostDelayedTask(id_, from_here, task, delay); | 46 return WebThread::PostDelayedTask(id_, from_here, task, delay); |
46 } | 47 } |
47 | 48 |
48 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 49 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
49 const base::Closure& task, | 50 const base::Closure& task, |
50 base::TimeDelta delay) override { | 51 base::TimeDelta delay) override { |
51 return WebThread::PostNonNestableDelayedTask(id_, from_here, task, delay); | 52 return WebThread::PostNonNestableDelayedTask(id_, from_here, task, delay); |
52 } | 53 } |
53 | 54 |
54 bool RunsTasksOnCurrentThread() const override { | 55 bool RunsTasksOnCurrentThread() const override { |
55 return WebThread::CurrentlyOn(id_); | 56 return WebThread::CurrentlyOn(id_); |
56 } | 57 } |
57 | 58 |
58 protected: | 59 protected: |
59 ~WebThreadTaskRunner() override {} | 60 ~WebThreadMessageLoopProxy() override {} |
60 | 61 |
61 private: | 62 private: |
62 WebThread::ID id_; | 63 WebThread::ID id_; |
63 DISALLOW_COPY_AND_ASSIGN(WebThreadTaskRunner); | 64 DISALLOW_COPY_AND_ASSIGN(WebThreadMessageLoopProxy); |
64 }; | 65 }; |
65 | 66 |
66 // A separate helper is used just for the task runners, in order to avoid | 67 // A separate helper is used just for the proxies, in order to avoid needing |
67 // needing to initialize the globals to create a task runner. | 68 // to initialize the globals to create a proxy. |
68 struct WebThreadTaskRunners { | 69 struct WebThreadProxies { |
69 WebThreadTaskRunners() { | 70 WebThreadProxies() { |
70 for (int i = 0; i < WebThread::ID_COUNT; ++i) { | 71 for (int i = 0; i < WebThread::ID_COUNT; ++i) { |
71 task_runners[i] = new WebThreadTaskRunner(static_cast<WebThread::ID>(i)); | 72 proxies[i] = new WebThreadMessageLoopProxy(static_cast<WebThread::ID>(i)); |
72 } | 73 } |
73 } | 74 } |
74 | 75 |
75 scoped_refptr<base::SingleThreadTaskRunner> task_runners[WebThread::ID_COUNT]; | 76 scoped_refptr<base::MessageLoopProxy> proxies[WebThread::ID_COUNT]; |
76 }; | 77 }; |
77 | 78 |
78 base::LazyInstance<WebThreadTaskRunners>::Leaky g_task_runners = | 79 base::LazyInstance<WebThreadProxies>::Leaky g_proxies = |
79 LAZY_INSTANCE_INITIALIZER; | 80 LAZY_INSTANCE_INITIALIZER; |
80 | 81 |
81 struct WebThreadGlobals { | 82 struct WebThreadGlobals { |
82 WebThreadGlobals() | 83 WebThreadGlobals() |
83 : blocking_pool(new base::SequencedWorkerPool(3, "WebBlocking")) { | 84 : blocking_pool(new base::SequencedWorkerPool(3, "WebBlocking")) { |
84 memset(threads, 0, WebThread::ID_COUNT * sizeof(threads[0])); | 85 memset(threads, 0, WebThread::ID_COUNT * sizeof(threads[0])); |
85 memset(thread_delegates, 0, | 86 memset(thread_delegates, 0, |
86 WebThread::ID_COUNT * sizeof(thread_delegates[0])); | 87 WebThread::ID_COUNT * sizeof(thread_delegates[0])); |
87 } | 88 } |
88 | 89 |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 base::TimeDelta delay) { | 444 base::TimeDelta delay) { |
444 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 445 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, |
445 false); | 446 false); |
446 } | 447 } |
447 | 448 |
448 // static | 449 // static |
449 bool WebThread::PostTaskAndReply(ID identifier, | 450 bool WebThread::PostTaskAndReply(ID identifier, |
450 const tracked_objects::Location& from_here, | 451 const tracked_objects::Location& from_here, |
451 const base::Closure& task, | 452 const base::Closure& task, |
452 const base::Closure& reply) { | 453 const base::Closure& reply) { |
453 return GetTaskRunnerForThread(identifier) | 454 return GetMessageLoopProxyForThread(identifier) |
454 ->PostTaskAndReply(from_here, task, reply); | 455 ->PostTaskAndReply(from_here, task, reply); |
455 } | 456 } |
456 | 457 |
457 // static | 458 // static |
458 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { | 459 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { |
459 if (g_globals == nullptr) | 460 if (g_globals == nullptr) |
460 return false; | 461 return false; |
461 | 462 |
462 // This shouldn't use MessageLoop::current() since it uses LazyInstance which | 463 // This shouldn't use MessageLoop::current() since it uses LazyInstance which |
463 // may be deleted by ~AtExitManager when a WorkerPool thread calls this | 464 // may be deleted by ~AtExitManager when a WorkerPool thread calls this |
464 // function. | 465 // function. |
465 // http://crbug.com/63678 | 466 // http://crbug.com/63678 |
466 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; | 467 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; |
467 base::MessageLoop* cur_message_loop = base::MessageLoop::current(); | 468 base::MessageLoop* cur_message_loop = base::MessageLoop::current(); |
468 WebThreadGlobals& globals = g_globals.Get(); | 469 WebThreadGlobals& globals = g_globals.Get(); |
469 for (int i = 0; i < ID_COUNT; ++i) { | 470 for (int i = 0; i < ID_COUNT; ++i) { |
470 if (globals.threads[i] && | 471 if (globals.threads[i] && |
471 globals.threads[i]->message_loop() == cur_message_loop) { | 472 globals.threads[i]->message_loop() == cur_message_loop) { |
472 *identifier = globals.threads[i]->identifier_; | 473 *identifier = globals.threads[i]->identifier_; |
473 return true; | 474 return true; |
474 } | 475 } |
475 } | 476 } |
476 | 477 |
477 return false; | 478 return false; |
478 } | 479 } |
479 | 480 |
480 // static | 481 // static |
481 scoped_refptr<base::SingleThreadTaskRunner> WebThread::GetTaskRunnerForThread( | 482 scoped_refptr<base::MessageLoopProxy> WebThread::GetMessageLoopProxyForThread( |
482 ID identifier) { | 483 ID identifier) { |
483 return g_task_runners.Get().task_runners[identifier]; | 484 return g_proxies.Get().proxies[identifier]; |
484 } | 485 } |
485 | 486 |
486 // static | 487 // static |
487 base::MessageLoop* WebThread::UnsafeGetMessageLoopForThread(ID identifier) { | 488 base::MessageLoop* WebThread::UnsafeGetMessageLoopForThread(ID identifier) { |
488 if (g_globals == nullptr) | 489 if (g_globals == nullptr) |
489 return nullptr; | 490 return nullptr; |
490 | 491 |
491 WebThreadGlobals& globals = g_globals.Get(); | 492 WebThreadGlobals& globals = g_globals.Get(); |
492 base::AutoLock lock(globals.lock); | 493 base::AutoLock lock(globals.lock); |
493 base::Thread* thread = globals.threads[identifier]; | 494 base::Thread* thread = globals.threads[identifier]; |
494 DCHECK(thread); | 495 DCHECK(thread); |
495 base::MessageLoop* loop = thread->message_loop(); | 496 base::MessageLoop* loop = thread->message_loop(); |
496 return loop; | 497 return loop; |
497 } | 498 } |
498 | 499 |
499 // static | 500 // static |
500 void WebThreadImpl::SetDelegate(ID identifier, WebThreadDelegate* delegate) { | 501 void WebThreadImpl::SetDelegate(ID identifier, WebThreadDelegate* delegate) { |
501 using base::subtle::AtomicWord; | 502 using base::subtle::AtomicWord; |
502 WebThreadGlobals& globals = g_globals.Get(); | 503 WebThreadGlobals& globals = g_globals.Get(); |
503 AtomicWord* storage = | 504 AtomicWord* storage = |
504 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); | 505 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); |
505 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 506 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
506 storage, reinterpret_cast<AtomicWord>(delegate)); | 507 storage, reinterpret_cast<AtomicWord>(delegate)); |
507 | 508 |
508 // This catches registration when previously registered. | 509 // This catches registration when previously registered. |
509 DCHECK(!delegate || !old_pointer); | 510 DCHECK(!delegate || !old_pointer); |
510 } | 511 } |
511 | 512 |
512 } // namespace web | 513 } // namespace web |
OLD | NEW |