Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2012 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 // CancelableTaskTracker posts tasks (in the form of a Closure) to a TaskRunner,
      6 // and is able to cancel the task later if it's not needed anymore. On
      7 // destruction, CancelableTaskTracker will cancel all tracked tasks.
      8 //
      9 // Each cancelable task can be associated with a reply (also a Closure). After
     10 // the task is run on the TaskRunner, |reply| will be posted back to originating
     11 // TaskRunner.
     12 //
     13 // NOTE:
     14 //
     15 // CancelableCallback (base/cancelable_callback.h) and WeakPtr binding are
     16 // preferred solutions for canceling a task. However, they don't support
     17 // cancelation from another thread. This is sometimes a performance critical
     18 // requirement. E.g. We need to cancel database lookup task on DB thread when
     19 // user changes inputed text. If it is performance critical to do a best effort
     20 // cancelation of a task, then CancelableTaskTracker is appropriate, otherwise
     21 // use one of the other mechanisms.
     22 //
     23 // THREAD-SAFETY:
     24 //
     25 // 1. CancelableTaskTracker objects are not thread safe. They must be created,
     26 // used, and destroyed on the originating thread that posts the task. It's safe
     27 // to destroy a CancelableTaskTracker while there are outstanding tasks. This is
     28 // commonly used to cancel all outstanding tasks.
     29 //
     30 // 2. Both task and reply are deleted on the originating thread.
     31 //
     32 // 3. IsCanceledCallback is thread safe and can be run or deleted on any thread.
     33 
     34 #ifndef CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
     35 #define CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
     36 
     37 #include "base/basictypes.h"
     38 #include "base/callback.h"
     39 #include "base/containers/hash_tables.h"
     40 #include "base/memory/weak_ptr.h"
     41 #include "base/threading/thread_checker.h"
     42 
     43 namespace base {
     44 class CancellationFlag;
     45 class TaskRunner;
     46 }  // namespace base
     47 
     48 namespace tracked_objects {
     49 class Location;
     50 }  // namespace tracked_objects
     51 
     52 class CancelableTaskTracker {
     53  public:
     54   // All values except kBadTaskId are valid.
     55   typedef int64 TaskId;
     56   static const TaskId kBadTaskId;
     57 
     58   typedef base::Callback<bool()> IsCanceledCallback;
     59 
     60   CancelableTaskTracker();
     61 
     62   // Cancels all tracked tasks.
     63   ~CancelableTaskTracker();
     64 
     65   TaskId PostTask(base::TaskRunner* task_runner,
     66                   const tracked_objects::Location& from_here,
     67                   const base::Closure& task);
     68 
     69   TaskId PostTaskAndReply(base::TaskRunner* task_runner,
     70                           const tracked_objects::Location& from_here,
     71                           const base::Closure& task,
     72                           const base::Closure& reply);
     73 
     74   // Creates a tracked TaskId and an associated IsCanceledCallback. Client can
     75   // later call TryCancel() with the returned TaskId, and run |is_canceled_cb|
     76   // from any thread to check whether the TaskId is canceled.
     77   //
     78   // The returned task ID is tracked until the last copy of
     79   // |is_canceled_cb| is destroyed.
     80   //
     81   // Note. This function is used to address some special cancelation requirement
     82   // in existing code. You SHOULD NOT need this function in new code.
     83   TaskId NewTrackedTaskId(IsCanceledCallback* is_canceled_cb);
     84 
     85   // After calling this function, |task| and |reply| will not run. If the
     86   // cancelation happens when |task| is running or has finished running, |reply|
     87   // will not run. If |reply| is running or has finished running, cancellation
     88   // is a noop.
     89   //
     90   // Note. It's OK to cancel a |task| for more than once. The later calls are
     91   // noops.
     92   void TryCancel(TaskId id);
     93 
     94   // It's OK to call this function for more than once. The later calls are
     95   // noops.
     96   void TryCancelAll();
     97 
     98   // Returns true iff there are in-flight tasks that are still being
     99   // tracked.
    100   bool HasTrackedTasks() const;
    101 
    102  private:
    103   void Track(TaskId id, base::CancellationFlag* flag);
    104   void Untrack(TaskId id);
    105 
    106   base::hash_map<TaskId, base::CancellationFlag*> task_flags_;
    107   base::WeakPtrFactory<CancelableTaskTracker> weak_factory_;
    108 
    109   TaskId next_id_;
    110   base::ThreadChecker thread_checker_;
    111 
    112   DISALLOW_COPY_AND_ASSIGN(CancelableTaskTracker);
    113 };
    114 
    115 #endif  // CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
    116