xref: /aosp_15_r20/external/ot-br-posix/src/common/task_runner.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2021, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * This file defines the Task Runner that executes tasks on the mainloop.
32  */
33 
34 #ifndef OTBR_COMMON_TASK_RUNNER_HPP_
35 #define OTBR_COMMON_TASK_RUNNER_HPP_
36 
37 #include <openthread-br/config.h>
38 
39 #include <chrono>
40 #include <functional>
41 #include <future>
42 #include <mutex>
43 #include <queue>
44 #include <set>
45 
46 #include "common/code_utils.hpp"
47 #include "common/mainloop.hpp"
48 #include "common/time.hpp"
49 
50 namespace otbr {
51 
52 /**
53  * This class implements the Task Runner that executes
54  * tasks on the mainloop.
55  */
56 class TaskRunner : public MainloopProcessor, private NonCopyable
57 {
58 public:
59     /**
60      * This type represents the generic executable task.
61      */
62     template <class T> using Task = std::function<T(void)>;
63 
64     /**
65      * This type represents a unique task ID to an delayed task.
66      *
67      * Note: A valid task ID is never zero.
68      */
69     typedef uint64_t TaskId;
70 
71     /**
72      * This constructor initializes the Task Runner instance.
73      */
74     TaskRunner(void);
75 
76     /**
77      * This destructor destroys the Task Runner instance.
78      */
79     ~TaskRunner(void) override;
80 
81     /**
82      * This method posts a task to the task runner and returns immediately.
83      *
84      * Tasks are executed sequentially and follow the First-Come-First-Serve rule.
85      * It is safe to call this method in different threads concurrently.
86      *
87      * @param[in] aTask  The task to be executed.
88      */
89     void Post(Task<void> aTask);
90 
91     /**
92      * This method posts a task to the task runner and returns immediately.
93      *
94      * The task will be executed on the mainloop after `aDelay` milliseconds from now.
95      * It is safe to call this method in different threads concurrently.
96      *
97      * @param[in] aDelay  The delay before executing the task (in milliseconds).
98      * @param[in] aTask   The task to be executed.
99      *
100      * @returns  The unique task ID of the delayed task.
101      */
102     TaskId Post(Milliseconds aDelay, Task<void> aTask);
103 
104     /**
105      * This method cancels a delayed task from the task runner.
106      * It is safe to call this method in different threads concurrently.
107      *
108      * @param[in] aTaskId  The unique task ID of the delayed task to cancel.
109      */
110     void Cancel(TaskId aTaskId);
111 
112     /**
113      * This method posts a task and waits for the completion of the task.
114      *
115      * Tasks are executed sequentially and follow the First-Come-First-Serve rule.
116      * This method must be called in a thread other than the mainloop thread. Otherwise,
117      * the caller will be blocked forever.
118      *
119      * @returns The result returned by the task @p aTask.
120      */
PostAndWait(const Task<T> & aTask)121     template <class T> T PostAndWait(const Task<T> &aTask)
122     {
123         std::promise<T> pro;
124 
125         Post([&pro, &aTask]() { pro.set_value(aTask()); });
126 
127         return pro.get_future().get();
128     }
129 
130     void Update(MainloopContext &aMainloop) override;
131     void Process(const MainloopContext &aMainloop) override;
132 
133 private:
134     enum
135     {
136         kRead  = 0,
137         kWrite = 1,
138     };
139 
140     struct DelayedTask
141     {
142         friend class Comparator;
143 
144         struct Comparator
145         {
operator ()otbr::TaskRunner::DelayedTask::Comparator146             bool operator()(const DelayedTask &aLhs, const DelayedTask &aRhs) const { return aRhs < aLhs; }
147         };
148 
DelayedTaskotbr::TaskRunner::DelayedTask149         DelayedTask(TaskId aTaskId, Milliseconds aDelay, Task<void> aTask)
150             : mTaskId(aTaskId)
151             , mDeadline(Clock::now() + aDelay)
152             , mTask(std::move(aTask))
153         {
154         }
155 
operator <otbr::TaskRunner::DelayedTask156         bool operator<(const DelayedTask &aOther) const
157         {
158             return mDeadline <= aOther.mDeadline || (mDeadline == aOther.mDeadline && mTaskId < aOther.mTaskId);
159         }
160 
GetTimeExecuteotbr::TaskRunner::DelayedTask161         Timepoint GetTimeExecute(void) const { return mDeadline; }
162 
163         TaskId     mTaskId;
164         Timepoint  mDeadline;
165         Task<void> mTask;
166     };
167 
168     TaskId PushTask(Milliseconds aDelay, Task<void> aTask);
169     void   PopTasks(void);
170 
171     // The event fds which are used to wakeup the mainloop
172     // when there are pending tasks in the task queue.
173     int mEventFd[2];
174 
175     std::priority_queue<DelayedTask, std::vector<DelayedTask>, DelayedTask::Comparator> mTaskQueue;
176 
177     std::set<TaskId> mActiveTaskIds;
178     TaskId           mNextTaskId = 1;
179 
180     // The mutex which protects the `mTaskQueue` from being
181     // simultaneously accessed by multiple threads.
182     std::mutex mTaskQueueMutex;
183 };
184 
185 } // namespace otbr
186 
187 #endif // OTBR_COMMON_TASK_RUNNER_HPP_
188