Home | History | Annotate | Download | only in base
      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 
     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 
     25 DelayedUniqueNotifier::~DelayedUniqueNotifier() {
     26 }
     27 
     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 
     42 void DelayedUniqueNotifier::Cancel() {
     43   next_notification_time_ = base::TimeTicks();
     44 }
     45 
     46 bool DelayedUniqueNotifier::HasPendingNotification() const {
     47   return notification_pending_ && !next_notification_time_.is_null();
     48 }
     49 
     50 base::TimeTicks DelayedUniqueNotifier::Now() const {
     51   return base::TimeTicks::Now();
     52 }
     53 
     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