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)35WorkerThreadTicker::WorkerThreadTicker(int tick_interval) 36 : timer_thread_("worker_thread_ticker"), 37 is_running_(false), 38 tick_interval_(tick_interval) { 39 } 40 ~WorkerThreadTicker()41WorkerThreadTicker::~WorkerThreadTicker() { 42 Stop(); 43 } 44 RegisterTickHandler(Callback * tick_handler)45bool 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)56bool 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()74bool 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()87bool 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()98void WorkerThreadTicker::ScheduleTimerTask() { 99 timer_thread_.message_loop()->PostDelayedTask(FROM_HERE, new TimerTask(this), 100 tick_interval_); 101 } 102