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