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