Home | History | Annotate | Download | only in child
      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
      3 // found in the LICENSE file.
      4 
      5 #include "content/child/worker_task_runner.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/lazy_instance.h"
      9 #include "base/logging.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/observer_list.h"
     12 
     13 using blink::WebWorkerRunLoop;
     14 
     15 namespace content {
     16 
     17 namespace {
     18 
     19 class RunClosureTask : public WebWorkerRunLoop::Task {
     20  public:
     21   RunClosureTask(const base::Closure& task) : task_(task) {}
     22   virtual ~RunClosureTask() {}
     23   virtual void Run() {
     24     task_.Run();
     25   }
     26  private:
     27   base::Closure task_;
     28 };
     29 
     30 } // namespace
     31 
     32 struct WorkerTaskRunner::ThreadLocalState {
     33   ThreadLocalState(int id, const WebWorkerRunLoop& loop)
     34       : id_(id), run_loop_(loop) {
     35   }
     36   int id_;
     37   WebWorkerRunLoop run_loop_;
     38   ObserverList<WorkerTaskRunner::Observer> stop_observers_;
     39 };
     40 
     41 WorkerTaskRunner::WorkerTaskRunner() {
     42   // Start worker ids at 1, 0 is reserved for the main thread.
     43   int id = id_sequence_.GetNext();
     44   DCHECK(!id);
     45 }
     46 
     47 bool WorkerTaskRunner::PostTask(
     48     int id, const base::Closure& closure) {
     49   DCHECK(id > 0);
     50   base::AutoLock locker(loop_map_lock_);
     51   IDToLoopMap::iterator found = loop_map_.find(id);
     52   if (found == loop_map_.end())
     53     return false;
     54   return found->second.postTask(new RunClosureTask(closure));
     55 }
     56 
     57 int WorkerTaskRunner::PostTaskToAllThreads(const base::Closure& closure) {
     58   base::AutoLock locker(loop_map_lock_);
     59   IDToLoopMap::iterator it;
     60   for (it = loop_map_.begin(); it != loop_map_.end(); ++it)
     61     it->second.postTask(new RunClosureTask(closure));
     62   return static_cast<int>(loop_map_.size());
     63 }
     64 
     65 int WorkerTaskRunner::CurrentWorkerId() {
     66   if (!current_tls_.Get())
     67     return 0;
     68   return current_tls_.Get()->id_;
     69 }
     70 
     71 WorkerTaskRunner* WorkerTaskRunner::Instance() {
     72   static base::LazyInstance<WorkerTaskRunner>::Leaky
     73       worker_task_runner = LAZY_INSTANCE_INITIALIZER;
     74   return worker_task_runner.Pointer();
     75 }
     76 
     77 void WorkerTaskRunner::AddStopObserver(Observer* obs) {
     78   DCHECK(CurrentWorkerId() > 0);
     79   current_tls_.Get()->stop_observers_.AddObserver(obs);
     80 }
     81 
     82 void WorkerTaskRunner::RemoveStopObserver(Observer* obs) {
     83   DCHECK(CurrentWorkerId() > 0);
     84   current_tls_.Get()->stop_observers_.RemoveObserver(obs);
     85 }
     86 
     87 WorkerTaskRunner::~WorkerTaskRunner() {
     88 }
     89 
     90 void WorkerTaskRunner::OnWorkerRunLoopStarted(const WebWorkerRunLoop& loop) {
     91   DCHECK(!current_tls_.Get());
     92   int id = id_sequence_.GetNext();
     93   current_tls_.Set(new ThreadLocalState(id, loop));
     94 
     95   base::AutoLock locker_(loop_map_lock_);
     96   loop_map_[id] = loop;
     97 }
     98 
     99 void WorkerTaskRunner::OnWorkerRunLoopStopped(const WebWorkerRunLoop& loop) {
    100   DCHECK(current_tls_.Get());
    101   FOR_EACH_OBSERVER(Observer, current_tls_.Get()->stop_observers_,
    102                     OnWorkerRunLoopStopped());
    103   {
    104     base::AutoLock locker(loop_map_lock_);
    105     DCHECK(loop_map_[CurrentWorkerId()] == loop);
    106     loop_map_.erase(CurrentWorkerId());
    107   }
    108   delete current_tls_.Get();
    109   current_tls_.Set(NULL);
    110 }
    111 
    112 }  // namespace content
    113