1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHRE_PLATFORM_LINUX_TASK_UTIL_TASK_MANAGER_H_
18 #define CHRE_PLATFORM_LINUX_TASK_UTIL_TASK_MANAGER_H_
19 
20 #include <chrono>
21 #include <condition_variable>
22 #include <mutex>
23 #include <optional>
24 #include <thread>
25 
26 #include "chre/platform/linux/task_util/task.h"
27 #include "chre/util/non_copyable.h"
28 #include "chre/util/priority_queue.h"
29 #include "chre/util/singleton.h"
30 
31 namespace chre {
32 
33 using task_manager_internal::Task;
34 
35 /**
36  * A class to manage a thread that executes arbitrary tasks. These tasks can
37  * repeat or be a singular execution. The manager will always execute the next
38  * task in chronological order.
39  */
40 class TaskManager : public NonCopyable {
41  public:
42   /**
43    * Construct a new Task Manager object.
44    */
45   TaskManager();
46 
47   /**
48    * Destroy the Task Manager object.
49    */
50   ~TaskManager();
51 
52   /**
53    * Adds a task to the queue for execution. The manager calls the function func
54    * during execution. If intervalOrDelay > 0 and isOneShot is false, the task
55    * will repeat every intervalOrDelay nanoseconds. If intervalOrDelay is > 0
56    * and isOneShot is true, the task will be executed only once after a delay of
57    * intervalOrDelay. If intervalOrDelay == 0, the task will be executed only
58    * once with no delay.
59    *
60    * @param func                     the function to call.
61    * @param intervalOrDelay          the interval to repeat.
62    * @param isOneShot                if true, the task should be executed only
63    * once with a delay of intervalOrDelay.
64    * @return                         the ID of the Task object or an empty
65    * Optional<> when there is an error.
66    */
67   std::optional<uint32_t> addTask(
68       const Task::TaskFunction &func,
69       std::chrono::nanoseconds intervalOrDelay = std::chrono::nanoseconds(0),
70       bool isOneShot = false);
71 
72   /**
73    * Cancels the task with the taskId.
74    *
75    * @param taskId                   the ID of the task.
76    * @return bool                    success.
77    */
78   bool cancelTask(uint32_t taskId);
79 
80   /**
81    * Empties the task queue without execution. This call is blocking.
82    */
83   void flushTasks();
84 
85   /**
86    * Stops the task manager by flushing all tasks and stopping the thread.
87    * This call is blocking.
88    */
89   void flushAndStop();
90 
91  private:
92   /**
93    * The run function for the execution thread.
94    */
95   void run();
96 
97   /**
98    * The queue of tasks.
99    *
100    * We use a chre::PriorityQueue here instead of a std::priority_queue because
101    * the chre::PriorityQueue allows container iterator access and the other does
102    * not.
103    */
104   PriorityQueue<Task, std::greater<Task>> mQueue;
105 
106   /**
107    * The current task being executed.
108    */
109   Task *mCurrentTask;
110 
111   /**
112    * The execution thread.
113    */
114   std::thread mThread;
115 
116   /**
117    * If true, continue executing in the thread. If false, stop executing in the
118    * thread.
119    */
120   bool mContinueRunningThread;
121 
122   /**
123    * The ID counter for Tasks; keeps the Task's ID unique.
124    */
125   uint32_t mCurrentId;
126 
127   /**
128    * The mutex to protect access to the queue.
129    */
130   std::mutex mMutex;
131 
132   /**
133    * The condition variable to signal to the execution thread to process more
134    * tasks (the queue is not empty).
135    */
136   std::condition_variable mConditionVariable;
137 };
138 
139 // Provide an alias to the TaskManager singleton.
140 typedef Singleton<TaskManager> TaskManagerSingleton;
141 
142 }  // namespace chre
143 
144 #endif  // CHRE_PLATFORM_LINUX_TASK_UTIL_TASK_MANAGER_H_
145