• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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 "chrome/common/worker_thread_ticker.h"
6 
7 #include <algorithm>
8 
9 #include "base/logging.h"
10 #include "base/message_loop.h"
11 #include "base/task.h"
12 #include "base/threading/thread.h"
13 
14 class WorkerThreadTicker::TimerTask : public Task {
15  public:
TimerTask(WorkerThreadTicker * ticker)16   explicit TimerTask(WorkerThreadTicker* ticker) : ticker_(ticker) {
17   }
18 
Run()19   virtual void Run() {
20     // When the ticker is running, the handler list CANNOT be modified.
21     // So we can do the enumeration safely without a lock
22     TickHandlerListType* handlers = &ticker_->tick_handler_list_;
23     for (TickHandlerListType::const_iterator i = handlers->begin();
24          i != handlers->end(); ++i) {
25       (*i)->OnTick();
26     }
27 
28     ticker_->ScheduleTimerTask();
29   }
30 
31  private:
32   WorkerThreadTicker* ticker_;
33 };
34 
WorkerThreadTicker(int tick_interval)35 WorkerThreadTicker::WorkerThreadTicker(int tick_interval)
36     : timer_thread_("worker_thread_ticker"),
37       is_running_(false),
38       tick_interval_(tick_interval) {
39 }
40 
~WorkerThreadTicker()41 WorkerThreadTicker::~WorkerThreadTicker() {
42   Stop();
43 }
44 
RegisterTickHandler(Callback * tick_handler)45 bool WorkerThreadTicker::RegisterTickHandler(Callback *tick_handler) {
46   DCHECK(tick_handler);
47   base::AutoLock lock(lock_);
48   // You cannot change the list of handlers when the timer is running.
49   // You need to call Stop first.
50   if (IsRunning())
51     return false;
52   tick_handler_list_.push_back(tick_handler);
53   return true;
54 }
55 
UnregisterTickHandler(Callback * tick_handler)56 bool WorkerThreadTicker::UnregisterTickHandler(Callback *tick_handler) {
57   DCHECK(tick_handler);
58   base::AutoLock lock(lock_);
59   // You cannot change the list of handlers when the timer is running.
60   // You need to call Stop first.
61   if (IsRunning()) {
62     return false;
63   }
64   TickHandlerListType::iterator index = std::remove(tick_handler_list_.begin(),
65                                                     tick_handler_list_.end(),
66                                                     tick_handler);
67   if (index == tick_handler_list_.end()) {
68     return false;
69   }
70   tick_handler_list_.erase(index, tick_handler_list_.end());
71   return true;
72 }
73 
Start()74 bool WorkerThreadTicker::Start() {
75   // Do this in a lock because we don't want 2 threads to
76   // call Start at the same time
77   base::AutoLock lock(lock_);
78   if (IsRunning())
79     return false;
80   if (!timer_thread_.Start())
81     return false;
82   is_running_ = true;
83   ScheduleTimerTask();
84   return true;
85 }
86 
Stop()87 bool WorkerThreadTicker::Stop() {
88   // Do this in a lock because we don't want 2 threads to
89   // call Stop at the same time
90   base::AutoLock lock(lock_);
91   if (!IsRunning())
92     return false;
93   is_running_ = false;
94   timer_thread_.Stop();
95   return true;
96 }
97 
ScheduleTimerTask()98 void WorkerThreadTicker::ScheduleTimerTask() {
99   timer_thread_.message_loop()->PostDelayedTask(FROM_HERE, new TimerTask(this),
100                                                 tick_interval_);
101 }
102