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