[email protected] | d9b1478 | 2010-04-15 08:08:07 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 5 | #include "chrome/common/worker_thread_ticker.h" |
6 | |||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 7 | #include <algorithm> |
8 | |||||
9 | #include "base/logging.h" | ||||
[email protected] | d9b1478 | 2010-04-15 08:08:07 | [diff] [blame] | 10 | #include "base/message_loop.h" |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 11 | #include "base/task.h" |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 12 | #include "base/thread.h" |
13 | |||||
14 | class WorkerThreadTicker::TimerTask : public Task { | ||||
15 | public: | ||||
[email protected] | 4a3dab2 | 2009-11-11 17:36:50 | [diff] [blame] | 16 | explicit TimerTask(WorkerThreadTicker* ticker) : ticker_(ticker) { |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 17 | } |
18 | |||||
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 | |||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 35 | WorkerThreadTicker::WorkerThreadTicker(int tick_interval) |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 36 | : timer_thread_("worker_thread_ticker"), |
37 | is_running_(false), | ||||
38 | tick_interval_(tick_interval) { | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 39 | } |
40 | |||||
41 | WorkerThreadTicker::~WorkerThreadTicker() { | ||||
42 | Stop(); | ||||
43 | } | ||||
44 | |||||
45 | bool WorkerThreadTicker::RegisterTickHandler(Callback *tick_handler) { | ||||
46 | DCHECK(tick_handler); | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 47 | AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 48 | // You cannot change the list of handlers when the timer is running. |
49 | // You need to call Stop first. | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 50 | if (IsRunning()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 51 | return false; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 52 | tick_handler_list_.push_back(tick_handler); |
53 | return true; | ||||
54 | } | ||||
55 | |||||
56 | bool WorkerThreadTicker::UnregisterTickHandler(Callback *tick_handler) { | ||||
57 | DCHECK(tick_handler); | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 58 | AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 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 | |||||
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 | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 77 | AutoLock lock(lock_); |
78 | if (IsRunning()) | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 79 | return false; |
[email protected] | 6314e6f6 | 2009-07-15 16:07:14 | [diff] [blame] | 80 | if (!timer_thread_.Start()) |
81 | return false; | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 82 | is_running_ = true; |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 83 | ScheduleTimerTask(); |
84 | return true; | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 85 | } |
86 | |||||
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 | ||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 90 | AutoLock lock(lock_); |
91 | if (!IsRunning()) | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 92 | return false; |
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 93 | is_running_ = false; |
94 | timer_thread_.Stop(); | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 95 | return true; |
96 | } | ||||
97 | |||||
[email protected] | d195f60 | 2009-01-14 17:23:19 | [diff] [blame] | 98 | void WorkerThreadTicker::ScheduleTimerTask() { |
99 | timer_thread_.message_loop()->PostDelayedTask(FROM_HERE, new TimerTask(this), | ||||
100 | tick_interval_); | ||||
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 101 | } |