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 class TaskletScheduler;
49 
50 /**
51  * @addtogroup core-tasklet
52  *
53  * @brief
54  *   This module includes definitions for tasklets and the tasklet scheduler.
55  *
56  * @{
57  *
58  */
59 
60 /**
61  * This class is used to represent a tasklet.
62  *
63  */
64 class Tasklet : public InstanceLocator
65 {
66 public:
67     /**
68      * This class implements the tasklet scheduler.
69      *
70      */
71     class Scheduler : private NonCopyable
72     {
73         friend class Tasklet;
74 
75     public:
76         /**
77          * This constructor initializes the object.
78          *
79          */
Scheduler(void)80         Scheduler(void)
81             : mTail(nullptr)
82         {
83         }
84 
85         /**
86          * This method indicates whether or not there are tasklets pending.
87          *
88          * @retval TRUE   If there are tasklets pending.
89          * @retval FALSE  If there are no tasklets pending.
90          *
91          */
AreTaskletsPending(void) const92         bool AreTaskletsPending(void) const { return mTail != nullptr; }
93 
94         /**
95          * This method processes all tasklets queued when this is called.
96          *
97          */
98         void ProcessQueuedTasklets(void);
99 
100     private:
101         void PostTasklet(Tasklet &aTasklet);
102 
103         Tasklet *mTail; // A circular singly linked-list
104     };
105 
106     /**
107      * This function reference is called when the tasklet is run.
108      *
109      * @param[in]  aTasklet  A reference to the tasklet being run.
110      *
111      */
112     typedef void (&Handler)(Tasklet &aTasklet);
113 
114     /**
115      * This constructor creates a tasklet instance.
116      *
117      * @param[in]  aInstance   A reference to the OpenThread instance object.
118      * @param[in]  aHandler    A pointer to a function that is called when the tasklet is run.
119      *
120      */
Tasklet(Instance & aInstance,Handler aHandler)121     Tasklet(Instance &aInstance, Handler aHandler)
122         : InstanceLocator(aInstance)
123         , mHandler(aHandler)
124         , mNext(nullptr)
125     {
126     }
127 
128     /**
129      * This method puts the tasklet on the tasklet scheduler run queue.
130      *
131      * If the tasklet is already posted, no change is made and run queue stays as before.
132      *
133      */
134     void Post(void);
135 
136     /**
137      * This method indicates whether the tasklet is posted or not.
138      *
139      * @retval TRUE  The tasklet is posted.
140      * @retval FALSE The tasklet is not posted.
141      *
142      */
IsPosted(void) const143     bool IsPosted(void) const { return (mNext != nullptr); }
144 
145 private:
RunTask(void)146     void RunTask(void) { mHandler(*this); }
147 
148     Handler  mHandler;
149     Tasklet *mNext;
150 };
151 
152 /**
153  * This class defines a tasklet that also maintains a user context pointer.
154  *
155  * In typical `Tasklet` use, in the handler callback, the owner of the tasklet is determined using `GetOwner<Type>`
156  * method. This method works if there is a single instance of `Type` within OpenThread instance hierarchy. The
157  * `TaskletContext` is intended for cases where there may be multiple instances of the same class/type using a `Tasklet`
158  * object. `TaskletContext` will store a context `void *` information.
159  *
160  */
161 class TaskletContext : public Tasklet
162 {
163 public:
164     /**
165      * This constructor creates a tasklet instance.
166      *
167      * @param[in]  aInstance   A reference to the OpenThread instance.
168      * @param[in]  aHandler    A pointer to a function that is called when the tasklet is run.
169      * @param[in]  aContext    A pointer to an arbitrary context information.
170      *
171      */
TaskletContext(Instance & aInstance,Handler aHandler,void * aContext)172     TaskletContext(Instance &aInstance, Handler aHandler, void *aContext)
173         : Tasklet(aInstance, aHandler)
174         , mContext(aContext)
175     {
176     }
177 
178     /**
179      * This method returns the pointer to the arbitrary context information.
180      *
181      * @returns Pointer to the arbitrary context information.
182      *
183      */
GetContext(void)184     void *GetContext(void) { return mContext; }
185 
186 private:
187     void *mContext;
188 };
189 
190 /**
191  * @}
192  *
193  */
194 
195 } // namespace ot
196 
197 #endif // TASKLET_HPP_
198