1 // Copyright 2016 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 #ifndef COMPONENTS_OFFLINE_PAGES_TASK_TASK_QUEUE_H_ 6 #define COMPONENTS_OFFLINE_PAGES_TASK_TASK_QUEUE_H_ 7 8 #include <memory> 9 10 #include "base/callback.h" 11 #include "base/containers/queue.h" 12 #include "base/macros.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/sequence_checker.h" 16 #include "components/offline_pages/task/task.h" 17 18 namespace base { 19 class SingleThreadTaskRunner; 20 } // namespace base 21 22 namespace offline_pages { 23 24 // Class for coordinating |Task|s in relation to access to a specific resource. 25 // As a task, we understand a set of asynchronous operations (possibly switching 26 // threads) that access a set of sensitive resource(s). Because the resource 27 // state is modified and individual steps of a task are asynchronous, allowing 28 // certain tasks to run in parallel may lead to incorrect results. This class 29 // allows for ordering of tasks in a FIFO manner, to ensure two tasks modifying 30 // a resources are not run at the same time. 31 // 32 // Consumers of this class should create an instance of TaskQueue and implement 33 // tasks that need to be run sequentially. New task will only be started when 34 // the previous one calls |Task::TaskComplete|. 35 // 36 // Methods on TaskQueue should be called from the same thread from which it 37 // is created. 38 class TaskQueue { 39 public: 40 class Delegate { 41 public: ~Delegate()42 virtual ~Delegate() {} 43 44 // Invoked once when TaskQueue reached 0 tasks. 45 virtual void OnTaskQueueIsIdle() = 0; 46 }; 47 48 explicit TaskQueue(Delegate* delegate); 49 ~TaskQueue(); 50 51 // Adds a task to the queue. Queue takes ownership of the task. 52 void AddTask(std::unique_ptr<Task> task); 53 // Whether the task queue has any pending (not-running) tasks. 54 bool HasPendingTasks() const; 55 // Whether there is a task currently running. 56 bool HasRunningTask() const; 57 58 private: 59 // Checks whether there are any tasks to run, as well as whether no task is 60 // currently running. When both are met, it will start the next task in the 61 // queue. 62 void StartTaskIfAvailable(); 63 64 void RunCurrentTask(); 65 66 // Callback for informing the queue that a task was completed. Can be called 67 // from any thread. 68 static void TaskCompletedCallback( 69 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 70 base::WeakPtr<TaskQueue> task_queue, 71 Task* task); 72 73 void TaskCompleted(Task* task); 74 75 void InformTaskQueueIsIdle(); 76 77 // This TaskQueue's task runner, set on construction using the instance 78 // assigned to the current thread. 79 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 80 81 // Owns and outlives this TaskQueue. 82 Delegate* delegate_; 83 84 // Currently running tasks. 85 std::unique_ptr<Task> current_task_; 86 87 // A FIFO queue of tasks that will be run using this task queue. 88 base::queue<std::unique_ptr<Task>> tasks_; 89 90 SEQUENCE_CHECKER(sequence_checker_); 91 92 base::WeakPtrFactory<TaskQueue> weak_ptr_factory_{this}; 93 94 DISALLOW_COPY_AND_ASSIGN(TaskQueue); 95 }; 96 97 } // namespace offline_pages 98 99 #endif // COMPONENTS_OFFLINE_PAGES_TASK_TASK_QUEUE_H_ 100