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