15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CancelableTaskTracker posts tasks (in the form of a Closure) to a TaskRunner,
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and is able to cancel the task later if it's not needed anymore. On
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destruction, CancelableTaskTracker will cancel all tracked tasks.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each cancelable task can be associated with a reply (also a Closure). After
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the task is run on the TaskRunner, |reply| will be posted back to originating
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TaskRunner.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CancelableCallback (base/cancelable_callback.h) and WeakPtr binding are
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preferred solutions for canceling a task. However, they don't support
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancelation from another thread. This is sometimes a performance critical
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requirement. E.g. We need to cancel database lookup task on DB thread when
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user changes inputed text. If it is performance critical to do a best effort
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancelation of a task, then CancelableTaskTracker is appropriate, otherwise
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use one of the other mechanisms.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THREAD-SAFETY:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. CancelableTaskTracker objects are not thread safe. They must be created,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used, and destroyed on the originating thread that posts the task. It's safe
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to destroy a CancelableTaskTracker while there are outstanding tasks. This is
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// commonly used to cancel all outstanding tasks.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Both task and reply are deleted on the originating thread.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 3. IsCanceledCallback is thread safe and can be run or deleted on any thread.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_checker.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CancellationFlag;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TaskRunner;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tracked_objects {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Location;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tracked_objects
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CancelableTaskTracker {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All values except kBadTaskId are valid.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef int64 TaskId;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const TaskId kBadTaskId;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef base::Callback<bool()> IsCanceledCallback;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelableTaskTracker();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels all tracked tasks.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~CancelableTaskTracker();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskId PostTask(base::TaskRunner* task_runner,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const tracked_objects::Location& from_here,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const base::Closure& task);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskId PostTaskAndReply(base::TaskRunner* task_runner,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const tracked_objects::Location& from_here,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const base::Closure& task,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const base::Closure& reply);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates a tracked TaskId and an associated IsCanceledCallback. Client can
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // later call TryCancel() with the returned TaskId, and run |is_canceled_cb|
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from any thread to check whether the TaskId is canceled.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The returned task ID is tracked until the last copy of
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |is_canceled_cb| is destroyed.
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note. This function is used to address some special cancelation requirement
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in existing code. You SHOULD NOT need this function in new code.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TaskId NewTrackedTaskId(IsCanceledCallback* is_canceled_cb);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After calling this function, |task| and |reply| will not run. If the
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cancelation happens when |task| is running or has finished running, |reply|
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will not run. If |reply| is running or has finished running, cancellation
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a noop.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note. It's OK to cancel a |task| for more than once. The later calls are
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // noops.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TryCancel(TaskId id);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's OK to call this function for more than once. The later calls are
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // noops.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TryCancelAll();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true iff there are in-flight tasks that are still being
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tracked.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HasTrackedTasks() const;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Track(TaskId id, base::CancellationFlag* flag);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Untrack(TaskId id);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::hash_map<TaskId, base::CancellationFlag*> task_flags_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<CancelableTaskTracker> weak_factory_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskId next_id_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadChecker thread_checker_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CancelableTaskTracker);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_COMMON_CANCELABLE_TASK_TRACKER_H_
116