| 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 |