Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: components/timers/alarm_timer_chromeos.cc

Issue 2398753003: Use FileDescriptorWatcher in AlarmTimer. (Closed)
Patch Set: fix build error Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/timers/alarm_timer_chromeos.h ('k') | components/timers/alarm_timer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/timers/alarm_timer_chromeos.h" 5 #include "components/timers/alarm_timer_chromeos.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <sys/timerfd.h> 8 #include <sys/timerfd.h>
9
10 #include <algorithm>
9 #include <utility> 11 #include <utility>
10 12
11 #include "base/bind.h" 13 #include "base/bind.h"
12 #include "base/bind_helpers.h" 14 #include "base/debug/task_annotator.h"
13 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
14 #include "base/lazy_instance.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/macros.h" 17 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/pending_task.h" 18 #include "base/pending_task.h"
19 #include "base/threading/thread.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
22 20
23 namespace timers { 21 namespace timers {
24 namespace {
25 // This class represents the IO thread that the AlarmTimer::Delegate may use for
26 // watching file descriptors if it gets called from a thread that does not have
27 // a MessageLoopForIO. It is a lazy global instance because it may not always
28 // be necessary.
29 class RtcAlarmIOThread : public base::Thread {
30 public:
31 RtcAlarmIOThread() : Thread("RTC Alarm IO Thread") {
32 CHECK(
33 StartWithOptions(base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
34 }
35 ~RtcAlarmIOThread() override { Stop(); }
36 };
37 22
38 base::LazyInstance<RtcAlarmIOThread> g_io_thread = LAZY_INSTANCE_INITIALIZER; 23 AlarmTimer::AlarmTimer(bool retain_user_task, bool is_repeating)
24 : base::Timer(retain_user_task, is_repeating),
25 alarm_fd_(timerfd_create(CLOCK_REALTIME_ALARM, 0)),
Chirantan Ekbote 2016/10/06 18:41:51 Does this mean it's now ok to make blocking system
fdoray 2016/10/06 18:57:33 No it's not ok. After the migration to TaskSchedul
26 weak_factory_(this) {}
39 27
40 } // namespace 28 AlarmTimer::~AlarmTimer() {
41 29 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
42 // Watches a MessageLoop and runs a callback if that MessageLoop will be 30 Stop();
43 // destroyed.
44 class AlarmTimer::MessageLoopObserver
45 : public base::MessageLoop::DestructionObserver {
46 public:
47 // Constructs a MessageLoopObserver that will observe |message_loop| and will
48 // call |on_will_be_destroyed_callback| when |message_loop| is about to be
49 // destroyed.
50 MessageLoopObserver(base::MessageLoop* message_loop,
51 base::Closure on_will_be_destroyed_callback)
52 : message_loop_(message_loop),
53 on_will_be_destroyed_callback_(on_will_be_destroyed_callback) {
54 DCHECK(message_loop_);
55 message_loop_->AddDestructionObserver(this);
56 }
57
58 ~MessageLoopObserver() override {
59 // If |message_loop_| was destroyed, then this class will have already
60 // unregistered itself. Doing it again will trigger a warning.
61 if (message_loop_)
62 message_loop_->RemoveDestructionObserver(this);
63 }
64
65 // base::MessageLoop::DestructionObserver override.
66 void WillDestroyCurrentMessageLoop() override {
67 message_loop_->RemoveDestructionObserver(this);
68 message_loop_ = NULL;
69
70 on_will_be_destroyed_callback_.Run();
71 }
72
73 private:
74 // The MessageLoop that this class should watch. Is a weak pointer.
75 base::MessageLoop* message_loop_;
76
77 // The callback to run when |message_loop_| will be destroyed.
78 base::Closure on_will_be_destroyed_callback_;
79
80 DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
81 };
82
83 // This class manages a Real Time Clock (RTC) alarm, a feature that is available
84 // from linux version 3.11 onwards. It creates a file descriptor for the RTC
85 // alarm timer and then watches that file descriptor to see when it can be read
86 // without blocking, indicating that the timer has fired.
87 //
88 // A major problem for this class is that watching file descriptors is only
89 // available on a MessageLoopForIO but there is no guarantee the timer is going
90 // to be created on one. To get around this, the timer has a dedicated thread
91 // with a MessageLoopForIO that posts tasks back to the thread that started the
92 // timer.
93 class AlarmTimer::Delegate
94 : public base::RefCountedThreadSafe<AlarmTimer::Delegate>,
95 public base::MessageLoopForIO::Watcher {
96 public:
97 // Construct a Delegate for the AlarmTimer. It should be safe to call
98 // |on_timer_fired_callback| multiple times.
99 explicit Delegate(base::Closure on_timer_fired_callback);
100
101 // Returns true if the system timer managed by this delegate is capable of
102 // waking the system from suspend.
103 bool CanWakeFromSuspend();
104
105 // Resets the timer to fire after |delay| has passed. Cancels any
106 // pre-existing delay.
107 void Reset(base::TimeDelta delay);
108
109 // Stops the currently running timer. It should be safe to call this even if
110 // the timer is not running.
111 void Stop();
112
113 // Sets a hook that will be called when the timer fires and a task has been
114 // queued on |origin_task_runner_|. Used by tests to wait until a task is
115 // pending in the MessageLoop.
116 void SetTimerFiredCallbackForTest(base::Closure test_callback);
117
118 // base::MessageLoopForIO::Watcher overrides.
119 void OnFileCanReadWithoutBlocking(int fd) override;
120 void OnFileCanWriteWithoutBlocking(int fd) override;
121
122 private:
123 friend class base::RefCountedThreadSafe<Delegate>;
124 ~Delegate() override;
125
126 // Actually performs the system calls to set up the timer. This must be
127 // called on a MessageLoopForIO.
128 void ResetImpl(base::TimeDelta delay, int reset_sequence_number);
129
130 // Callback that is run when the timer fires. Must be run on
131 // |origin_task_runner_|.
132 void OnTimerFired(int reset_sequence_number);
133
134 // File descriptor associated with the alarm timer.
135 int alarm_fd_;
136
137 // Task runner which initially started the timer.
138 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
139
140 // Callback that should be run when the timer fires.
141 base::Closure on_timer_fired_callback_;
142
143 // Hook used by tests to be notified when the timer has fired and a task has
144 // been queued in the MessageLoop.
145 base::Closure on_timer_fired_callback_for_test_;
146
147 // Manages watching file descriptors.
148 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> fd_watcher_;
149
150 // The sequence numbers of the last Reset() call handled respectively on
151 // |origin_task_runner_| and on the MessageLoopForIO used for watching the
152 // timer file descriptor. Note that these can be the same MessageLoop.
153 // OnTimerFired() runs |on_timer_fired_callback_| only if the sequence number
154 // it receives from the MessageLoopForIO matches
155 // |origin_reset_sequence_number_|.
156 int origin_reset_sequence_number_;
157 int io_reset_sequence_number_;
158
159 DISALLOW_COPY_AND_ASSIGN(Delegate);
160 };
161
162 AlarmTimer::Delegate::Delegate(base::Closure on_timer_fired_callback)
163 : alarm_fd_(timerfd_create(CLOCK_REALTIME_ALARM, 0)),
164 on_timer_fired_callback_(on_timer_fired_callback),
165 origin_reset_sequence_number_(0),
166 io_reset_sequence_number_(0) {
167 // The call to timerfd_create above may fail. This is the only indication
168 // that CLOCK_REALTIME_ALARM is not supported on this system.
169 DPLOG_IF(INFO, (alarm_fd_ == -1))
170 << "CLOCK_REALTIME_ALARM not supported on this system";
171 } 31 }
172 32
173 AlarmTimer::Delegate::~Delegate() { 33 void AlarmTimer::Stop() {
174 if (alarm_fd_ != -1) 34 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
175 close(alarm_fd_);
176 }
177 35
178 bool AlarmTimer::Delegate::CanWakeFromSuspend() { 36 if (!base::Timer::is_running())
179 return alarm_fd_ != -1; 37 return;
180 }
181 38
182 void AlarmTimer::Delegate::Reset(base::TimeDelta delay) { 39 if (!CanWakeFromSuspend()) {
183 // Get a task runner for the current message loop. When the timer fires, we 40 base::Timer::Stop();
184 // will
185 // post tasks to this proxy to let the parent timer know.
186 origin_task_runner_ = base::ThreadTaskRunnerHandle::Get();
187
188 // Increment the sequence number. Used to invalidate any events that have
189 // been queued but not yet run since the last time Reset() was called.
190 origin_reset_sequence_number_++;
191
192 // Calling timerfd_settime with a zero delay actually clears the timer so if
193 // the user has requested a zero delay timer, we need to handle it
194 // differently. We queue the task here but we still go ahead and call
195 // timerfd_settime with the zero delay anyway to cancel any previous delay
196 // that might have been programmed.
197 if (delay <= base::TimeDelta::FromMicroseconds(0)) {
198 // The timerfd_settime documentation is vague on what happens when it is
199 // passed a negative delay. We can sidestep the issue by ensuring that
200 // the delay is 0.
201 delay = base::TimeDelta::FromMicroseconds(0);
202 origin_task_runner_->PostTask(
203 FROM_HERE,
204 base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
205 origin_reset_sequence_number_));
206 }
207
208 // Run ResetImpl() on a MessageLoopForIO.
209 if (base::MessageLoopForIO::IsCurrent()) {
210 ResetImpl(delay, origin_reset_sequence_number_);
211 } else {
212 g_io_thread.Pointer()->task_runner()->PostTask(
213 FROM_HERE,
214 base::Bind(&Delegate::ResetImpl, scoped_refptr<Delegate>(this), delay,
215 origin_reset_sequence_number_));
216 }
217 }
218
219 void AlarmTimer::Delegate::Stop() {
220 // Stop the RTC from a MessageLoopForIO.
221 if (!base::MessageLoopForIO::IsCurrent()) {
222 g_io_thread.Pointer()->task_runner()->PostTask(
223 FROM_HERE, base::Bind(&Delegate::Stop, scoped_refptr<Delegate>(this)));
224 return; 41 return;
225 } 42 }
226 43
227 // Stop watching for events. 44 // Cancel any previous callbacks.
228 fd_watcher_.reset(); 45 weak_factory_.InvalidateWeakPtrs();
229 46
230 // Now clear the timer. 47 base::Timer::set_is_running(false);
231 DCHECK_NE(alarm_fd_, -1); 48 alarm_fd_watcher_.reset();
232 itimerspec blank_time = {}; 49 pending_task_.reset();
233 if (timerfd_settime(alarm_fd_, 0, &blank_time, NULL) < 0) 50
234 PLOG(ERROR) << "Unable to clear alarm time. Timer may still fire."; 51 if (!base::Timer::retain_user_task())
52 base::Timer::set_user_task(base::Closure());
235 } 53 }
236 54
237 void AlarmTimer::Delegate::OnFileCanReadWithoutBlocking(int fd) { 55 void AlarmTimer::Reset() {
238 DCHECK_EQ(alarm_fd_, fd); 56 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
57 DCHECK(!base::Timer::user_task().is_null());
239 58
240 // Read from the fd to ack the event. 59 if (!CanWakeFromSuspend()) {
241 char val[sizeof(uint64_t)]; 60 base::Timer::Reset();
242 if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t))) 61 return;
243 PLOG(DFATAL) << "Unable to read from timer file descriptor.";
244
245 // Make sure that the parent timer is informed on the proper message loop.
246 if (origin_task_runner_->RunsTasksOnCurrentThread()) {
247 OnTimerFired(io_reset_sequence_number_);
248 } else {
249 origin_task_runner_->PostTask(
250 FROM_HERE,
251 base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
252 io_reset_sequence_number_));
253 }
254 }
255
256 void AlarmTimer::Delegate::OnFileCanWriteWithoutBlocking(int fd) {
257 NOTREACHED();
258 }
259
260 void AlarmTimer::Delegate::SetTimerFiredCallbackForTest(
261 base::Closure test_callback) {
262 on_timer_fired_callback_for_test_ = test_callback;
263 }
264
265 void AlarmTimer::Delegate::ResetImpl(base::TimeDelta delay,
266 int reset_sequence_number) {
267 DCHECK(base::MessageLoopForIO::IsCurrent());
268 DCHECK_NE(alarm_fd_, -1);
269
270 // Store the sequence number in the IO thread variable. When the timer
271 // fires, we will bind this value to the OnTimerFired callback to ensure
272 // that we do the right thing if the timer gets reset.
273 io_reset_sequence_number_ = reset_sequence_number;
274
275 // If we were already watching the fd, this will stop watching it.
276 fd_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
277
278 // Start watching the fd to see when the timer fires.
279 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
280 alarm_fd_, false, base::MessageLoopForIO::WATCH_READ,
281 fd_watcher_.get(), this)) {
282 LOG(ERROR) << "Error while attempting to watch file descriptor for RTC "
283 << "alarm. Timer will not fire.";
284 } 62 }
285 63
286 // Actually set the timer. This will also clear the pre-existing timer, if 64 // Cancel any previous callbacks and stop watching |alarm_fd_|.
287 // any. 65 weak_factory_.InvalidateWeakPtrs();
66 alarm_fd_watcher_.reset();
67
68 // Ensure that the delay is not negative.
69 const base::TimeDelta delay =
70 std::max(base::TimeDelta(), base::Timer::GetCurrentDelay());
71
72 // Set up the pending task.
73 base::Timer::set_desired_run_time(
74 delay.is_zero() ? base::TimeTicks() : base::TimeTicks::Now() + delay);
75 pending_task_ = base::MakeUnique<base::PendingTask>(
76 base::Timer::posted_from(), base::Timer::user_task(),
77 base::Timer::desired_run_time(), true /* nestable */);
78
79 // Set |alarm_fd_| to be signaled when the delay expires. If the delay is
80 // zero, |alarm_fd_| will never be signaled. This overrides the previous
81 // delay, if any.
288 itimerspec alarm_time = {}; 82 itimerspec alarm_time = {};
289 alarm_time.it_value.tv_sec = delay.InSeconds(); 83 alarm_time.it_value.tv_sec = delay.InSeconds();
290 alarm_time.it_value.tv_nsec = 84 alarm_time.it_value.tv_nsec =
291 (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) * 85 (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
292 base::Time::kNanosecondsPerMicrosecond; 86 base::Time::kNanosecondsPerMicrosecond;
293 if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0) 87 if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0)
294 PLOG(ERROR) << "Error while setting alarm time. Timer will not fire"; 88 PLOG(ERROR) << "Error while setting alarm time. Timer will not fire";
89
90 // The timer is running.
91 base::Timer::set_is_running(true);
92
93 // If the delay is zero, post the task now.
94 if (delay.is_zero()) {
95 origin_task_runner_->PostTask(
96 FROM_HERE,
97 base::Bind(&AlarmTimer::OnTimerFired, weak_factory_.GetWeakPtr()));
98 } else {
99 // Otherwise, if the delay is not zero, generate a tracing event to indicate
100 // that the task was posted and watch |alarm_fd_|.
101 base::debug::TaskAnnotator().DidQueueTask("AlarmTimer::Reset",
102 *pending_task_);
103 alarm_fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
104 alarm_fd_, base::Bind(&AlarmTimer::OnAlarmFdReadableWithoutBlocking,
105 weak_factory_.GetWeakPtr()));
106 }
295 } 107 }
296 108
297 void AlarmTimer::Delegate::OnTimerFired(int reset_sequence_number) { 109 void AlarmTimer::OnAlarmFdReadableWithoutBlocking() {
298 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); 110 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
111 DCHECK(base::Timer::IsRunning());
299 112
300 // If a test wants to be notified when this function is about to run, then 113 // Read from |alarm_fd_| to ack the event.
301 // re-queue this task in the MessageLoop and run the test's callback. 114 char val[sizeof(uint64_t)];
302 if (!on_timer_fired_callback_for_test_.is_null()) { 115 if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t)))
303 origin_task_runner_->PostTask( 116 PLOG(DFATAL) << "Unable to read from timer file descriptor.";
304 FROM_HERE,
305 base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
306 reset_sequence_number));
307 117
308 on_timer_fired_callback_for_test_.Run(); 118 OnTimerFired();
309 on_timer_fired_callback_for_test_.Reset();
310 return;
311 }
312
313 // Check to make sure that the timer was not reset in the time between when
314 // this task was queued to run and now. If it was reset, then don't do
315 // anything.
316 if (reset_sequence_number != origin_reset_sequence_number_)
317 return;
318
319 on_timer_fired_callback_.Run();
320 }
321
322 AlarmTimer::AlarmTimer(bool retain_user_task, bool is_repeating)
323 : base::Timer(retain_user_task, is_repeating),
324 can_wake_from_suspend_(false),
325 origin_message_loop_(NULL),
326 weak_factory_(this) {
327 Init();
328 }
329
330 AlarmTimer::AlarmTimer(const tracked_objects::Location& posted_from,
331 base::TimeDelta delay,
332 const base::Closure& user_task,
333 bool is_repeating)
334 : base::Timer(posted_from, delay, user_task, is_repeating),
335 can_wake_from_suspend_(false),
336 origin_message_loop_(NULL),
337 weak_factory_(this) {
338 Init();
339 }
340
341 AlarmTimer::~AlarmTimer() {
342 Stop();
343 }
344
345 void AlarmTimer::SetTimerFiredCallbackForTest(base::Closure test_callback) {
346 delegate_->SetTimerFiredCallbackForTest(test_callback);
347 }
348
349 void AlarmTimer::Init() {
350 delegate_ = make_scoped_refptr(new AlarmTimer::Delegate(
351 base::Bind(&AlarmTimer::OnTimerFired, weak_factory_.GetWeakPtr())));
352 can_wake_from_suspend_ = delegate_->CanWakeFromSuspend();
353 }
354
355 void AlarmTimer::Stop() {
356 if (!base::Timer::is_running())
357 return;
358
359 if (!can_wake_from_suspend_) {
360 base::Timer::Stop();
361 return;
362 }
363
364 // Clear the running flag, stop the delegate, and delete the pending task.
365 base::Timer::set_is_running(false);
366 delegate_->Stop();
367 pending_task_.reset();
368
369 // Stop watching |origin_message_loop_|.
370 origin_message_loop_ = NULL;
371 message_loop_observer_.reset();
372
373 if (!base::Timer::retain_user_task())
374 base::Timer::set_user_task(base::Closure());
375 }
376
377 void AlarmTimer::Reset() {
378 if (!can_wake_from_suspend_) {
379 base::Timer::Reset();
380 return;
381 }
382
383 DCHECK(!base::Timer::user_task().is_null());
384 DCHECK(!origin_message_loop_ ||
385 origin_message_loop_->task_runner()->RunsTasksOnCurrentThread());
386
387 // Make sure that the timer will stop if the underlying message loop is
388 // destroyed.
389 if (!origin_message_loop_) {
390 origin_message_loop_ = base::MessageLoop::current();
391 message_loop_observer_.reset(new MessageLoopObserver(
392 origin_message_loop_,
393 base::Bind(&AlarmTimer::WillDestroyCurrentMessageLoop,
394 weak_factory_.GetWeakPtr())));
395 }
396
397 // Set up the pending task.
398 if (base::Timer::GetCurrentDelay() > base::TimeDelta::FromMicroseconds(0)) {
399 base::Timer::set_desired_run_time(base::TimeTicks::Now() +
400 base::Timer::GetCurrentDelay());
401 pending_task_.reset(new base::PendingTask(
402 base::Timer::posted_from(), base::Timer::user_task(),
403 base::Timer::desired_run_time(), true /* nestable */));
404 } else {
405 base::Timer::set_desired_run_time(base::TimeTicks());
406 pending_task_.reset(new base::PendingTask(base::Timer::posted_from(),
407 base::Timer::user_task()));
408 }
409 base::MessageLoop::current()->task_annotator()->DidQueueTask(
410 "AlarmTimer::Reset", *pending_task_);
411
412 // Now start up the timer.
413 delegate_->Reset(base::Timer::GetCurrentDelay());
414 base::Timer::set_is_running(true);
415 }
416
417 void AlarmTimer::WillDestroyCurrentMessageLoop() {
418 Stop();
419 } 119 }
420 120
421 void AlarmTimer::OnTimerFired() { 121 void AlarmTimer::OnTimerFired() {
422 if (!base::Timer::IsRunning()) 122 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
423 return; 123 DCHECK(base::Timer::IsRunning());
424
425 DCHECK(pending_task_.get()); 124 DCHECK(pending_task_.get());
426 125
427 // Take ownership of the pending user task, which is going to be cleared by 126 // Take ownership of the PendingTask to prevent it from being deleted if the
428 // the Stop() or Reset() functions below. 127 // AlarmTimer is deleted.
429 std::unique_ptr<base::PendingTask> pending_user_task( 128 const auto pending_user_task = std::move(pending_task_);
430 std::move(pending_task_));
431 129
432 // Re-schedule or stop the timer as requested. 130 base::WeakPtr<AlarmTimer> weak_ptr = weak_factory_.GetWeakPtr();
433 if (base::Timer::is_repeating())
434 Reset();
435 else
436 Stop();
437 131
132 // Run the task.
438 TRACE_TASK_EXECUTION("AlarmTimer::OnTimerFired", *pending_user_task); 133 TRACE_TASK_EXECUTION("AlarmTimer::OnTimerFired", *pending_user_task);
134 base::debug::TaskAnnotator().RunTask("AlarmTimer::Reset", *pending_user_task);
439 135
440 // Now run the user task. 136 // If the timer wasn't deleted, stopped or reset by the callback, reset or
441 base::MessageLoop::current()->task_annotator()->RunTask("AlarmTimer::Reset", 137 // stop it.
442 *pending_user_task); 138 if (weak_ptr.get()) {
139 if (base::Timer::is_repeating())
140 Reset();
141 else
142 Stop();
143 }
144 }
145
146 bool AlarmTimer::CanWakeFromSuspend() const {
147 return alarm_fd_ != -1;
443 } 148 }
444 149
445 OneShotAlarmTimer::OneShotAlarmTimer() : AlarmTimer(false, false) { 150 OneShotAlarmTimer::OneShotAlarmTimer() : AlarmTimer(false, false) {
446 } 151 }
447 152
448 OneShotAlarmTimer::~OneShotAlarmTimer() { 153 OneShotAlarmTimer::~OneShotAlarmTimer() {
449 } 154 }
450 155
451 RepeatingAlarmTimer::RepeatingAlarmTimer() : AlarmTimer(true, true) { 156 RepeatingAlarmTimer::RepeatingAlarmTimer() : AlarmTimer(true, true) {
452 } 157 }
453 158
454 RepeatingAlarmTimer::RepeatingAlarmTimer(
455 const tracked_objects::Location& posted_from,
456 base::TimeDelta delay,
457 const base::Closure& user_task)
458 : AlarmTimer(posted_from, delay, user_task, true) {
459 }
460
461 RepeatingAlarmTimer::~RepeatingAlarmTimer() { 159 RepeatingAlarmTimer::~RepeatingAlarmTimer() {
462 } 160 }
463 161
464 SimpleAlarmTimer::SimpleAlarmTimer() : AlarmTimer(true, false) { 162 SimpleAlarmTimer::SimpleAlarmTimer() : AlarmTimer(true, false) {
465 } 163 }
466 164
467 SimpleAlarmTimer::SimpleAlarmTimer(const tracked_objects::Location& posted_from,
468 base::TimeDelta delay,
469 const base::Closure& user_task)
470 : AlarmTimer(posted_from, delay, user_task, false) {
471 }
472
473 SimpleAlarmTimer::~SimpleAlarmTimer() { 165 SimpleAlarmTimer::~SimpleAlarmTimer() {
474 } 166 }
475 167
476 } // namespace timers 168 } // namespace timers
OLDNEW
« no previous file with comments | « components/timers/alarm_timer_chromeos.h ('k') | components/timers/alarm_timer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698