1 // Copyright 2013 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 "webkit/browser/fileapi/timed_task_helper.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/sequenced_task_runner.h" 10 11 namespace fileapi { 12 13 struct TimedTaskHelper::Tracker { 14 explicit Tracker(TimedTaskHelper* timer) : timer(timer) {} 15 16 ~Tracker() { 17 if (timer) 18 timer->tracker_ = NULL; 19 } 20 21 TimedTaskHelper* timer; 22 }; 23 24 TimedTaskHelper::TimedTaskHelper(base::SequencedTaskRunner* task_runner) 25 : task_runner_(task_runner), 26 tracker_(NULL) { 27 } 28 29 TimedTaskHelper::~TimedTaskHelper() { 30 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 31 if (tracker_) 32 tracker_->timer = NULL; 33 } 34 35 bool TimedTaskHelper::IsRunning() const { 36 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 37 return tracker_ != NULL; 38 } 39 40 void TimedTaskHelper::Start( 41 const tracked_objects::Location& posted_from, 42 base::TimeDelta delay, 43 const base::Closure& user_task) { 44 posted_from_ = posted_from; 45 delay_ = delay; 46 user_task_ = user_task; 47 Reset(); 48 } 49 50 void TimedTaskHelper::Reset() { 51 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 52 DCHECK(!user_task_.is_null()); 53 desired_run_time_ = base::TimeTicks::Now() + delay_; 54 55 if (tracker_) 56 return; 57 58 // Initialize the tracker for the first time. 59 tracker_ = new Tracker(this); 60 PostDelayedTask(make_scoped_ptr(tracker_), delay_); 61 } 62 63 // static 64 void TimedTaskHelper::Fired(scoped_ptr<Tracker> tracker) { 65 if (!tracker->timer) 66 return; 67 TimedTaskHelper* timer = tracker->timer; 68 timer->OnFired(tracker.Pass()); 69 } 70 71 void TimedTaskHelper::OnFired(scoped_ptr<Tracker> tracker) { 72 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 73 base::TimeTicks now = base::TimeTicks::Now(); 74 if (desired_run_time_ > now) { 75 PostDelayedTask(tracker.Pass(), desired_run_time_ - now); 76 return; 77 } 78 tracker.reset(); 79 base::Closure task = user_task_; 80 user_task_.Reset(); 81 task.Run(); 82 } 83 84 void TimedTaskHelper::PostDelayedTask(scoped_ptr<Tracker> tracker, 85 base::TimeDelta delay) { 86 task_runner_->PostDelayedTask( 87 posted_from_, 88 base::Bind(&TimedTaskHelper::Fired, base::Passed(&tracker)), 89 delay); 90 } 91 92 } // namespace fileapi 93