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 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 21 WorkerThreadTicker::~WorkerThreadTicker() { 22 Stop(); 23 } 24 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 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 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 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 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 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