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