• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "cc/base/delayed_unique_notifier.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/sequenced_task_runner.h"
11 
12 namespace cc {
13 
DelayedUniqueNotifier(base::SequencedTaskRunner * task_runner,const base::Closure & closure,const base::TimeDelta & delay)14 DelayedUniqueNotifier::DelayedUniqueNotifier(
15     base::SequencedTaskRunner* task_runner,
16     const base::Closure& closure,
17     const base::TimeDelta& delay)
18     : task_runner_(task_runner),
19       closure_(closure),
20       delay_(delay),
21       notification_pending_(false),
22       weak_ptr_factory_(this) {
23 }
24 
~DelayedUniqueNotifier()25 DelayedUniqueNotifier::~DelayedUniqueNotifier() {
26 }
27 
Schedule()28 void DelayedUniqueNotifier::Schedule() {
29   if (notification_pending_) {
30     next_notification_time_ = Now() + delay_;
31     return;
32   }
33 
34   next_notification_time_ = Now() + delay_;
35   task_runner_->PostDelayedTask(FROM_HERE,
36                                 base::Bind(&DelayedUniqueNotifier::NotifyIfTime,
37                                            weak_ptr_factory_.GetWeakPtr()),
38                                 delay_);
39   notification_pending_ = true;
40 }
41 
Cancel()42 void DelayedUniqueNotifier::Cancel() {
43   next_notification_time_ = base::TimeTicks();
44 }
45 
HasPendingNotification() const46 bool DelayedUniqueNotifier::HasPendingNotification() const {
47   return notification_pending_ && !next_notification_time_.is_null();
48 }
49 
Now() const50 base::TimeTicks DelayedUniqueNotifier::Now() const {
51   return base::TimeTicks::Now();
52 }
53 
NotifyIfTime()54 void DelayedUniqueNotifier::NotifyIfTime() {
55   // If next notifiaction time is not valid, then this schedule was canceled.
56   if (next_notification_time_.is_null()) {
57     notification_pending_ = false;
58     return;
59   }
60 
61   // If the notification was rescheduled or arrived too early for any other
62   // reason, then post another task instead of running the callback.
63   base::TimeTicks now = Now();
64   if (next_notification_time_ > now) {
65     task_runner_->PostDelayedTask(
66         FROM_HERE,
67         base::Bind(&DelayedUniqueNotifier::NotifyIfTime,
68                    weak_ptr_factory_.GetWeakPtr()),
69         next_notification_time_ - now);
70     return;
71   }
72 
73   // Note the order here is important since closure might schedule another run.
74   notification_pending_ = false;
75   closure_.Run();
76 }
77 
78 }  // namespace cc
79