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