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