summaryrefslogtreecommitdiffstats
path: root/webkit/browser/fileapi/timed_task_helper.cc
blob: 50d1dd00d9bfc3491df9364ff84e35f459cf39d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/browser/fileapi/timed_task_helper.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"

namespace fileapi {

struct TimedTaskHelper::Tracker {
  explicit Tracker(TimedTaskHelper* timer) : timer(timer) {}

  ~Tracker() {
    if (timer)
      timer->tracker_ = NULL;
  }

  TimedTaskHelper* timer;
};

TimedTaskHelper::TimedTaskHelper(base::SequencedTaskRunner* task_runner)
    : task_runner_(task_runner),
      tracker_(NULL) {
}

TimedTaskHelper::~TimedTaskHelper() {
  DCHECK(task_runner_->RunsTasksOnCurrentThread());
  if (tracker_)
    tracker_->timer = NULL;
}

bool TimedTaskHelper::IsRunning() const {
  DCHECK(task_runner_->RunsTasksOnCurrentThread());
  return tracker_ != NULL;
}

void TimedTaskHelper::Start(
    const tracked_objects::Location& posted_from,
    base::TimeDelta delay,
    const base::Closure& user_task) {
  posted_from_ = posted_from;
  delay_ = delay;
  user_task_ = user_task;
  Reset();
}

void TimedTaskHelper::Reset() {
  DCHECK(task_runner_->RunsTasksOnCurrentThread());
  DCHECK(!user_task_.is_null());
  desired_run_time_ = base::TimeTicks::Now() + delay_;

  if (tracker_)
    return;

  // Initialize the tracker for the first time.
  tracker_ = new Tracker(this);
  PostDelayedTask(make_scoped_ptr(tracker_), delay_);
}

// static
void TimedTaskHelper::Fired(scoped_ptr<Tracker> tracker) {
  if (!tracker->timer)
    return;
  TimedTaskHelper* timer = tracker->timer;
  timer->OnFired(tracker.Pass());
}

void TimedTaskHelper::OnFired(scoped_ptr<Tracker> tracker) {
  DCHECK(task_runner_->RunsTasksOnCurrentThread());
  base::TimeTicks now = base::TimeTicks::Now();
  if (desired_run_time_ > now) {
    PostDelayedTask(tracker.Pass(), desired_run_time_ - now);
    return;
  }
  tracker.reset();
  base::Closure task = user_task_;
  user_task_.Reset();
  task.Run();
}

void TimedTaskHelper::PostDelayedTask(scoped_ptr<Tracker> tracker,
                                      base::TimeDelta delay) {
  task_runner_->PostDelayedTask(
      posted_from_,
      base::Bind(&TimedTaskHelper::Fired, base::Passed(&tracker)),
      delay);
}

}  // namespace fileapi