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