Mistake on this page?
Report an issue in GitHub or email us
CallChainOfFunctionPointersWithContext.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2013 ARM Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
17 #define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
18 
19 #include <string.h>
21 #include "SafeBool.h"
22 
23 /**
24  * @addtogroup ble
25  * @{
26  * @addtogroup common
27  * @{
28  */
29 
30 /**
31  * Function like object hosting a list of FunctionPointerWithContext.
32  *
33  * Upon call, each FunctionPointerWithContext instance present in the object will
34  * be called in sequence with the initial parameters.
35  *
36  * It can be seen as a variation of the observer pattern this object being the
37  * observable, instances of the FunctionPointerWithContext being the observable
38  * and the notify/update operation being the function call.
39  *
40  * Example:
41  * @code
42  *
43  * CallChainOfFunctionPointersWithContext<void *> chain;
44  *
45  * void first(void *context) {
46  * printf("'first' function.\n");
47  * }
48  *
49  * void second(void *context) {
50  * printf("'second' function.\n");
51  * }
52  *
53  * class Test {
54  * public:
55  * void f(void *context) {
56  * printf("A::f (class member).\n");
57  * }
58  * };
59  *
60  * int main() {
61  * Test test;
62  *
63  * chain.add(second);
64  * chain.add_front(first);
65  * chain.add(&test, &Test::f);
66  *
67  * // will print:
68  * // 'second' function.
69  * // 'first' function.
70  * // A::f (class member).
71  * chain.call();
72  * }
73  * @endcode
74  *
75  * @note memory allocation is used to add new function like objects into the
76  * call chain.
77  *
78  * @tparam ContextType Type of the parameter accepted by the callbacks hosted
79  * in the object.
80  */
81 template <typename ContextType>
83  public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > {
84 public:
85  /**
86  * Alias of the FunctionPointerWithContext type this object can store.
87  */
89 
90 public:
91  /**
92  * Create an empty callchain.
93  */
95 
96  /**
97  * Destruction of the callchain.
98  */
100  {
101  clear();
102  }
103 
104  /**
105  * Add a function pointer at the front of the chain.
106  *
107  * @param[in] function A pointer to a void function.
108  *
109  * @return The FunctionPointerWithContext object created from @p function.
110  */
111  pFunctionPointerWithContext_t add(void (*function)(ContextType context))
112  {
113  return common_add(new FunctionPointerWithContext<ContextType>(function));
114  }
115 
116  /**
117  * Add a member function bound to its instance at the front of the chain.
118  *
119  * @param[in] tptr Pointer to the object to call the member function on.
120  * @param[in] mptr Pointer to the member function to be called.
121  *
122  * @return The FunctionPointerWithContext object created from @p tptr and
123  * @p mptr.
124  */
125  template<typename T>
126  pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context))
127  {
128  return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
129  }
130 
131  /**
132  * Add a FunctionPointerWithContext at the front of the chain.
133  *
134  * @param[in] func The FunctionPointerWithContext to add.
135  *
136  * @return The function object created for @p func.
137  */
138  pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType> &func)
139  {
140  return common_add(new FunctionPointerWithContext<ContextType>(func));
141  }
142 
143  /**
144  * Detach a function pointer from a callchain.
145  *
146  * @param[in] toDetach FunctionPointerWithContext instance to detach from
147  * this callchain.
148  *
149  * @return true if a function pointer has been detached and false otherwise.
150  *
151  * @note It is safe to remove a function pointer while
152  * call(ContextType) is traversing the chain.
153  */
155  {
156  pFunctionPointerWithContext_t current = chainHead;
157  pFunctionPointerWithContext_t previous = NULL;
158 
159  while (current) {
160  if(*current == toDetach) {
161  if(previous == NULL) {
162  if(currentCalled == current) {
163  currentCalled = NULL;
164  }
165  chainHead = current->getNext();
166  } else {
167  if(currentCalled == current) {
168  currentCalled = previous;
169  }
170  previous->chainAsNext(current->getNext());
171  }
172  delete current;
173  return true;
174  }
175 
176  previous = current;
177  current = current->getNext();
178  }
179 
180  return false;
181  }
182 
183  /**
184  * Remove all functions registered in the chain.
185  */
186  void clear(void)
187  {
188  pFunctionPointerWithContext_t fptr = chainHead;
189  while (fptr) {
190  pFunctionPointerWithContext_t deadPtr = fptr;
191  fptr = deadPtr->getNext();
192  delete deadPtr;
193  }
194 
195  chainHead = NULL;
196  }
197 
198  /**
199  * Check whether the callchain contains any callbacks.
200  *
201  * @return true if the callchain is not empty and false otherwise.
202  */
203  bool hasCallbacksAttached(void) const
204  {
205  return (chainHead != NULL);
206  }
207 
208  /**
209  * Call sequentially each member of the chain.
210  *
211  * @param[in] context Parameter to pass to the functions called.
212  */
213  void call(ContextType context)
214  {
215  ((const CallChainOfFunctionPointersWithContext*) this)->call(context);
216  }
217 
218  /**
219  * Call sequentially each member of the chain.
220  *
221  * @param[in] context Parameter to pass to the functions called.
222  */
223  void call(ContextType context) const
224  {
225  currentCalled = chainHead;
226 
227  while(currentCalled) {
228  currentCalled->call(context);
229  // if this was the head and the call removed the head
230  if(currentCalled == NULL) {
231  currentCalled = chainHead;
232  } else {
233  currentCalled = currentCalled->getNext();
234  }
235  }
236  }
237 
238  /**
239  * Call sequentially each member of the chain.
240  *
241  * @param[in] context Parameter to pass to the functions called.
242  *
243  * @code
244  *
245  * void first(bool);
246  * void second(bool);
247  *
248  * CallChainOfFunctionPointerWithContext<bool> foo;
249  *
250  * foo.attach(first);
251  * foo.attach(second);
252  *
253  * // call the callchain like a function
254  * foo(true);
255  *
256  * @endcode
257  */
258  void operator()(ContextType context) const
259  {
260  call(context);
261  }
262 
263  /**
264  * Test if the callchain is empty or not.
265  *
266  * @return true if the callchain is not empty and false otherwise.
267  *
268  * @note used by SafeBool to offer a safe boolean conversion.
269  *
270  * @code
271  * CallChainOfFunctionPointersWithContext<void *> chain;
272  *
273  * if (!chain) {
274  * // Do something if the chain is empty.
275  * }
276  *
277  * if (chain) {
278  * // Do something if the chain is not empty.
279  * }
280  * @endcode
281  *
282  */
283  bool toBool() const
284  {
285  return chainHead != NULL;
286  }
287 
288 private:
289  /**
290  * Add a callback to the head of the callchain.
291  *
292  * @return A pointer to the head of the callchain.
293  */
294  pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf)
295  {
296  if (chainHead == NULL) {
297  chainHead = pf;
298  } else {
299  pf->chainAsNext(chainHead);
300  chainHead = pf;
301  }
302 
303  return chainHead;
304  }
305 
306 private:
307  /**
308  * Pointer to the first callback of the callchain or NULL if the callchain
309  * is empty.
310  */
311  pFunctionPointerWithContext_t chainHead;
312 
313  /**
314  * Pointer to the function being called.
315  *
316  * It is used to maintain the data structure integrity if a function is
317  * removed during the call() operation.
318  *
319  * @note It has to be mutable to accomodate the const version of call(). The
320  * iterator doesn't leak outside the object; therefore, it remains seen as
321  * const from an external standpoint.
322  */
323  mutable pFunctionPointerWithContext_t currentCalled;
324 
325 
326  /* Disallow copy constructor and assignment operators. */
327 private:
330  );
333  );
334 };
335 
336 /**
337  * @}
338  * @}
339  */
340 
341 #endif
Function like object adapter over freestanding and member functions.
bool toBool() const
Test if the callchain is empty or not.
void call(ContextType context) const
Call sequentially each member of the chain.
pFunctionPointerWithContext_t add(T *tptr, void(T::*mptr)(ContextType context))
Add a member function bound to its instance at the front of the chain.
bool hasCallbacksAttached(void) const
Check whether the callchain contains any callbacks.
pFunctionPointerWithContext_t getNext(void) const
Access the next element in the call chain.
pFunctionPointerWithContext_t add(const FunctionPointerWithContext< ContextType > &func)
Add a FunctionPointerWithContext at the front of the chain.
pFunctionPointerWithContext_t add(void(*function)(ContextType context))
Add a function pointer at the front of the chain.
FunctionPointerWithContext< ContextType > * pFunctionPointerWithContext_t
Alias of the FunctionPointerWithContext type this object can store.
void call(ContextType context) const
Call the adapted function and functions chained to the instance.
virtual ~CallChainOfFunctionPointersWithContext()
Destruction of the callchain.
void call(ContextType context)
Call sequentially each member of the chain.
bool detach(const FunctionPointerWithContext< ContextType > &toDetach)
Detach a function pointer from a callchain.
Function like object hosting a list of FunctionPointerWithContext.
void operator()(ContextType context) const
Call sequentially each member of the chain.
Safe conversion of objects in boolean context.
Definition: SafeBool.h:111
void clear(void)
Remove all functions registered in the chain.
void chainAsNext(pFunctionPointerWithContext_t next)
Set a FunctionPointer instance as the next element in the chain of callable objects.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.