1 /* 2 * Copyright (c) 2016, 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 includes definitions for tasklets and the tasklet scheduler. 32 */ 33 34 #ifndef TASKLET_HPP_ 35 #define TASKLET_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stdio.h> 40 41 #include <openthread/tasklet.h> 42 43 #include "common/locator.hpp" 44 #include "common/non_copyable.hpp" 45 46 namespace ot { 47 48 /** 49 * @addtogroup core-tasklet 50 * 51 * @brief 52 * This module includes definitions for tasklets and the tasklet scheduler. 53 * 54 * @{ 55 */ 56 57 /** 58 * Is used to represent a tasklet. 59 */ 60 class Tasklet : public InstanceLocator 61 { 62 public: 63 /** 64 * Implements the tasklet scheduler. 65 */ 66 class Scheduler : private NonCopyable 67 { 68 friend class Tasklet; 69 70 public: 71 /** 72 * Initializes the object. 73 */ Scheduler(void)74 Scheduler(void) 75 : mTail(nullptr) 76 { 77 } 78 79 /** 80 * Indicates whether or not there are tasklets pending. 81 * 82 * @retval TRUE If there are tasklets pending. 83 * @retval FALSE If there are no tasklets pending. 84 */ AreTaskletsPending(void) const85 bool AreTaskletsPending(void) const { return mTail != nullptr; } 86 87 /** 88 * Processes all tasklets queued when this is called. 89 */ 90 void ProcessQueuedTasklets(void); 91 92 private: 93 void PostTasklet(Tasklet &aTasklet); 94 void RemoveTasklet(Tasklet &aTasklet); 95 96 Tasklet *mTail; // A circular singly linked-list 97 }; 98 99 /** 100 * Reference is called when the tasklet is run. 101 * 102 * @param[in] aTasklet A reference to the tasklet being run. 103 */ 104 typedef void (&Handler)(Tasklet &aTasklet); 105 106 /** 107 * Creates a tasklet instance. 108 * 109 * @param[in] aInstance A reference to the OpenThread instance object. 110 * @param[in] aHandler A pointer to a function that is called when the tasklet is run. 111 */ Tasklet(Instance & aInstance,Handler aHandler)112 Tasklet(Instance &aInstance, Handler aHandler) 113 : InstanceLocator(aInstance) 114 , mHandler(aHandler) 115 , mNext(nullptr) 116 { 117 } 118 119 /** 120 * Puts the tasklet on the tasklet scheduler run queue. 121 * 122 * If the tasklet is already posted, no change is made and run queue stays as before. 123 */ 124 void Post(void); 125 126 /** 127 * Removes the tasklet from the tasklet scheduler run queue. 128 * 129 * If the tasklet is not posted, no change is made and run queue stays as before. 130 */ 131 void Unpost(void); 132 133 /** 134 * Indicates whether the tasklet is posted or not. 135 * 136 * @retval TRUE The tasklet is posted. 137 * @retval FALSE The tasklet is not posted. 138 */ IsPosted(void) const139 bool IsPosted(void) const { return (mNext != nullptr); } 140 141 private: RunTask(void)142 void RunTask(void) { mHandler(*this); } 143 144 Handler mHandler; 145 Tasklet *mNext; 146 }; 147 148 /** 149 * Defines a tasklet owned by specific type and using a method on owner type as the callback. 150 * 151 * @tparam Owner The type of owner of this tasklet. 152 * @tparam HandleTaskletPtr A pointer to a non-static member method of `Owner` to use as tasklet handler. 153 * 154 * The `Owner` MUST be a type that is accessible using `InstanceLocator::Get<Owner>()`. 155 */ 156 template <typename Owner, void (Owner::*HandleTaskletPtr)(void)> class TaskletIn : public Tasklet 157 { 158 public: 159 /** 160 * Initializes the tasklet. 161 * 162 * @param[in] aInstance The OpenThread instance. 163 */ TaskletIn(Instance & aInstance)164 explicit TaskletIn(Instance &aInstance) 165 : Tasklet(aInstance, HandleTasklet) 166 { 167 } 168 169 private: 170 static void HandleTasklet(Tasklet &aTasklet); // Implemented in `instance.hpp` 171 }; 172 173 /** 174 * Defines a tasklet that also maintains a user context pointer. 175 * 176 * In typical `Tasklet` use, in the handler callback, the owner of the tasklet is determined using `GetOwner<Type>` 177 * method. This method works if there is a single instance of `Type` within OpenThread instance hierarchy. The 178 * `TaskletContext` is intended for cases where there may be multiple instances of the same class/type using a `Tasklet` 179 * object. `TaskletContext` will store a context `void *` information. 180 */ 181 class TaskletContext : public Tasklet 182 { 183 public: 184 /** 185 * Creates a tasklet instance. 186 * 187 * @param[in] aInstance A reference to the OpenThread instance. 188 * @param[in] aHandler A pointer to a function that is called when the tasklet is run. 189 * @param[in] aContext A pointer to an arbitrary context information. 190 */ TaskletContext(Instance & aInstance,Handler aHandler,void * aContext)191 TaskletContext(Instance &aInstance, Handler aHandler, void *aContext) 192 : Tasklet(aInstance, aHandler) 193 , mContext(aContext) 194 { 195 } 196 197 /** 198 * Returns the pointer to the arbitrary context information. 199 * 200 * @returns Pointer to the arbitrary context information. 201 */ GetContext(void)202 void *GetContext(void) { return mContext; } 203 204 private: 205 void *mContext; 206 }; 207 208 /** 209 * @} 210 */ 211 212 } // namespace ot 213 214 #endif // TASKLET_HPP_ 215