Avi Drissman | 3f7a9d8 | 2022-09-08 20:55:42 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 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 CC_RASTER_TASK_H_ |
| 6 | #define CC_RASTER_TASK_H_ |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
vmpstr | a6b3016 | 2017-01-12 20:23:03 | [diff] [blame] | 10 | #include <string> |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 11 | #include <vector> |
| 12 | |
Keishi Hattori | c1b0023 | 2022-11-22 09:04:26 | [diff] [blame] | 13 | #include "base/memory/raw_ptr.h" |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 14 | #include "base/memory/ref_counted.h" |
chrishtr | ac41ff9 | 2017-03-17 05:07:30 | [diff] [blame] | 15 | #include "cc/cc_export.h" |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 16 | |
| 17 | namespace cc { |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 18 | class Task; |
| 19 | |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 20 | // This class provides states to manage life cycle of a task and given below is |
| 21 | // how it is used by TaskGraphWorkQueue to process life cycle of a task. |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 22 | // Task is in kNew state when it is created. When task is added to |
| 23 | // |ready_to_run_tasks| then its state is changed to kScheduled. Task can be |
| 24 | // canceled from kNew state (not yet scheduled to run) or from kScheduled state, |
| 25 | // when new ScheduleTasks() is triggered and its state is changed to kCanceled. |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 26 | // When task is about to run it is added |running_tasks| and its state is |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 27 | // changed to kRunning. Once task finishes running, its state is changed to |
| 28 | // kFinished. Both kCanceled and kFinished tasks are added to |completed_tasks|. |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 29 | // ╔═════╗ |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 30 | // +------║ kNew║------+ |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 31 | // | ╚═════╝ | |
| 32 | // v v |
| 33 | // ┌───────────┐ ╔══════════╗ |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 34 | // │ kScheduled│------> ║ kCanceled║ |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 35 | // └───────────┘ ╚══════════╝ |
| 36 | // | |
| 37 | // v |
| 38 | // ┌─────────┐ ╔══════════╗ |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 39 | // │ kRunning│-------> ║ kFinished║ |
prashant.n | 06e1561 | 2016-05-26 17:35:21 | [diff] [blame] | 40 | // └─────────┘ ╚══════════╝ |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 41 | class CC_EXPORT TaskState { |
| 42 | public: |
vmpstr | a6b3016 | 2017-01-12 20:23:03 | [diff] [blame] | 43 | bool IsNew() const; |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 44 | bool IsScheduled() const; |
| 45 | bool IsRunning() const; |
| 46 | bool IsFinished() const; |
| 47 | bool IsCanceled() const; |
| 48 | |
| 49 | // Functions to change the state of task. These functions should be called |
| 50 | // only from TaskGraphWorkQueue where the life cycle of a task is decided or |
| 51 | // from tests. These functions are not thread-safe. Caller is responsible for |
| 52 | // thread safety. |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 53 | void Reset(); // Sets state to kNew. |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 54 | void DidSchedule(); |
| 55 | void DidStart(); |
| 56 | void DidFinish(); |
| 57 | void DidCancel(); |
| 58 | |
vmpstr | a6b3016 | 2017-01-12 20:23:03 | [diff] [blame] | 59 | std::string ToString() const; |
| 60 | |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 61 | private: |
| 62 | friend class Task; |
| 63 | |
| 64 | // Let only Task class create the TaskState. |
| 65 | TaskState(); |
| 66 | ~TaskState(); |
| 67 | |
Ho Cheung | 0636519 | 2023-09-14 17:09:54 | [diff] [blame] | 68 | enum class Value : uint16_t { |
| 69 | kNew, |
| 70 | kScheduled, |
| 71 | kRunning, |
| 72 | kFinished, |
| 73 | kCanceled |
| 74 | }; |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 75 | |
| 76 | Value value_; |
| 77 | }; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 78 | |
| 79 | // A task which can be run by a TaskGraphRunner. To run a Task, it should be |
| 80 | // inserted into a TaskGraph, which can then be scheduled on the |
| 81 | // TaskGraphRunner. |
| 82 | class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> { |
| 83 | public: |
| 84 | typedef std::vector<scoped_refptr<Task>> Vector; |
| 85 | |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 86 | TaskState& state() { return state_; } |
Linwan Song | b7f402a | 2018-12-11 17:50:57 | [diff] [blame] | 87 | void set_frame_number(int64_t frame_number) { frame_number_ = frame_number; } |
| 88 | int64_t frame_number() { return frame_number_; } |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 89 | |
Sreeja Kamishetty | fcea16b | 2023-06-08 18:23:25 | [diff] [blame] | 90 | // Unique trace flow id for the given task, used to connect the places where |
| 91 | // the task was posted from and the task itself. |
| 92 | uint64_t trace_task_id() { return trace_task_id_; } |
| 93 | void set_trace_task_id(uint64_t id) { trace_task_id_ = id; } |
| 94 | |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 95 | // Subclasses should implement this method. RunOnWorkerThread may be called |
| 96 | // on any thread, and subclasses are responsible for locking and thread |
| 97 | // safety. |
| 98 | virtual void RunOnWorkerThread() = 0; |
| 99 | |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 100 | protected: |
| 101 | friend class base::RefCountedThreadSafe<Task>; |
| 102 | |
| 103 | Task(); |
| 104 | virtual ~Task(); |
| 105 | |
prashant.n | d67b4b01 | 2016-04-25 19:36:05 | [diff] [blame] | 106 | private: |
| 107 | TaskState state_; |
Linwan Song | b7f402a | 2018-12-11 17:50:57 | [diff] [blame] | 108 | int64_t frame_number_ = -1; |
Sreeja Kamishetty | fcea16b | 2023-06-08 18:23:25 | [diff] [blame] | 109 | int64_t trace_task_id_ = 0; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 110 | }; |
| 111 | |
| 112 | // A task dependency graph describes the order in which to execute a set |
| 113 | // of tasks. Dependencies are represented as edges. Each node is assigned |
| 114 | // a category, a priority and a run count that matches the number of |
| 115 | // dependencies. Priority range from 0 (most favorable scheduling) to UINT16_MAX |
| 116 | // (least favorable). Categories range from 0 to UINT16_MAX. It is up to the |
| 117 | // implementation and its consumer to determine the meaning (if any) of a |
| 118 | // category. A TaskGraphRunner implementation may chose to prioritize certain |
| 119 | // categories over others, regardless of the individual priorities of tasks. |
| 120 | struct CC_EXPORT TaskGraph { |
vmpstr | 48f6e1fb | 2016-09-22 18:35:44 | [diff] [blame] | 121 | struct CC_EXPORT Node { |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 122 | typedef std::vector<Node> Vector; |
| 123 | |
Sreeja Kamishetty | fcea16b | 2023-06-08 18:23:25 | [diff] [blame] | 124 | Node(scoped_refptr<Task> new_task, |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 125 | uint16_t category, |
| 126 | uint16_t priority, |
vmpstr | 48f6e1fb | 2016-09-22 18:35:44 | [diff] [blame] | 127 | uint32_t dependencies); |
Vladimir Levin | f06d1cd7 | 2019-03-13 18:24:10 | [diff] [blame] | 128 | Node(const Node&) = delete; |
vmpstr | 48f6e1fb | 2016-09-22 18:35:44 | [diff] [blame] | 129 | Node(Node&& other); |
| 130 | ~Node(); |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 131 | |
Vladimir Levin | f06d1cd7 | 2019-03-13 18:24:10 | [diff] [blame] | 132 | Node& operator=(const Node&) = delete; |
vmpstr | 48f6e1fb | 2016-09-22 18:35:44 | [diff] [blame] | 133 | Node& operator=(Node&& other) = default; |
| 134 | |
| 135 | scoped_refptr<Task> task; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 136 | uint16_t category; |
| 137 | uint16_t priority; |
| 138 | uint32_t dependencies; |
| 139 | }; |
| 140 | |
| 141 | struct Edge { |
| 142 | typedef std::vector<Edge> Vector; |
| 143 | |
| 144 | Edge(const Task* task, Task* dependent) |
| 145 | : task(task), dependent(dependent) {} |
| 146 | |
Pâris | e6361d0 | 2023-07-19 09:00:43 | [diff] [blame] | 147 | raw_ptr<const Task, AcrossTasksDanglingUntriaged> task; |
| 148 | raw_ptr<Task, AcrossTasksDanglingUntriaged> dependent; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 149 | }; |
| 150 | |
| 151 | TaskGraph(); |
Vladimir Levin | f06d1cd7 | 2019-03-13 18:24:10 | [diff] [blame] | 152 | TaskGraph(const TaskGraph&) = delete; |
vmpstr | 48f6e1fb | 2016-09-22 18:35:44 | [diff] [blame] | 153 | TaskGraph(TaskGraph&& other); |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 154 | ~TaskGraph(); |
| 155 | |
Vladimir Levin | f06d1cd7 | 2019-03-13 18:24:10 | [diff] [blame] | 156 | TaskGraph& operator=(const TaskGraph&) = delete; |
| 157 | TaskGraph& operator=(TaskGraph&&) = default; |
| 158 | |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 159 | void Swap(TaskGraph* other); |
| 160 | void Reset(); |
| 161 | |
| 162 | Node::Vector nodes; |
| 163 | Edge::Vector edges; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame] | 164 | }; |
| 165 | |
| 166 | } // namespace cc |
| 167 | |
| 168 | #endif // CC_RASTER_TASK_H_ |