| // 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 "storage/browser/fileapi/timed_task_helper.h" |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/sequenced_task_runner.h" |
| |
| namespace storage { |
| |
| 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() { |
| 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 storage |