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