Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CallChainOfFunctionPointersWithContext.h Source File

CallChainOfFunctionPointersWithContext.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
00017 #define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
00018 
00019 #include <string.h>
00020 #include "FunctionPointerWithContext.h "
00021 #include "SafeBool.h "
00022 
00023 /**
00024  * @addtogroup ble
00025  * @{
00026  * @addtogroup common
00027  * @{
00028  */
00029 
00030 /**
00031  * Function like object hosting a list of FunctionPointerWithContext.
00032  *
00033  * Upon call, each FunctionPointerWithContext instance present in the object will
00034  * be called in sequence with the initial parameters.
00035  *
00036  * It can be seen as a variation of the observer pattern this object being the
00037  * observable, instances of the FunctionPointerWithContext being the observable
00038  * and the notify/update operation being the function call.
00039  *
00040  * Example:
00041  * @code
00042  *
00043  * CallChainOfFunctionPointersWithContext<void *> chain;
00044  *
00045  * void first(void *context) {
00046  *     printf("'first' function.\n");
00047  * }
00048  *
00049  * void second(void *context) {
00050  *     printf("'second' function.\n");
00051  * }
00052  *
00053  * class Test {
00054  * public:
00055  *     void f(void *context) {
00056  *         printf("A::f (class member).\n");
00057  *     }
00058  * };
00059  *
00060  * int main() {
00061  *     Test test;
00062  *
00063  *     chain.add(second);
00064  *     chain.add_front(first);
00065  *     chain.add(&test, &Test::f);
00066  *
00067  *     // will print:
00068  *     // 'second' function.
00069  *     // 'first' function.
00070  *     // A::f (class member).
00071  *     chain.call();
00072  * }
00073  * @endcode
00074  *
00075  * @note memory allocation is used to add new function like objects into the
00076  * call chain.
00077  *
00078  * @tparam ContextType Type of the parameter accepted by the callbacks hosted
00079  * in the object.
00080  */
00081 template <typename ContextType>
00082 class CallChainOfFunctionPointersWithContext :
00083     public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > {
00084 public:
00085     /**
00086      * Alias of the FunctionPointerWithContext type this object can store.
00087      */
00088     typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
00089 
00090 public:
00091     /**
00092      * Create an empty callchain.
00093      */
00094     CallChainOfFunctionPointersWithContext() : chainHead(NULL) { }
00095 
00096     /**
00097      * Destruction of the callchain.
00098      */
00099     virtual ~CallChainOfFunctionPointersWithContext()
00100     {
00101         clear();
00102     }
00103 
00104     /**
00105      * Add a function pointer at the front of the chain.
00106      *
00107      * @param[in] function A pointer to a void function.
00108      *
00109      * @return The FunctionPointerWithContext object created from @p function.
00110      */
00111     pFunctionPointerWithContext_t  add(void (*function)(ContextType context))
00112     {
00113         return common_add(new FunctionPointerWithContext<ContextType>(function));
00114     }
00115 
00116     /**
00117      * Add a member function bound to its instance at the front of the chain.
00118      *
00119      * @param[in] tptr Pointer to the object to call the member function on.
00120      * @param[in] mptr Pointer to the member function to be called.
00121      *
00122      * @return The FunctionPointerWithContext object created from @p tptr and
00123      * @p mptr.
00124      */
00125     template<typename T>
00126     pFunctionPointerWithContext_t  add(T *tptr, void (T::*mptr)(ContextType context))
00127     {
00128         return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
00129     }
00130 
00131     /**
00132      * Add a FunctionPointerWithContext at the front of the chain.
00133      *
00134      * @param[in] func The FunctionPointerWithContext to add.
00135      *
00136      * @return  The function object created for @p func.
00137      */
00138     pFunctionPointerWithContext_t  add(const FunctionPointerWithContext<ContextType> &func)
00139     {
00140         return common_add(new FunctionPointerWithContext<ContextType>(func));
00141     }
00142 
00143     /**
00144      * Detach a function pointer from a callchain.
00145      *
00146      * @param[in] toDetach FunctionPointerWithContext instance to detach from
00147      * this callchain.
00148      *
00149      * @return true if a function pointer has been detached and false otherwise.
00150      *
00151      * @note It is safe to remove a function pointer while
00152      * call(ContextType) is traversing the chain.
00153      */
00154     bool detach(const FunctionPointerWithContext<ContextType> &toDetach)
00155     {
00156         pFunctionPointerWithContext_t  current = chainHead;
00157         pFunctionPointerWithContext_t  previous = NULL;
00158 
00159         while (current) {
00160             if(*current == toDetach) {
00161                 if(previous == NULL) {
00162                     if(currentCalled == current) {
00163                         currentCalled = NULL;
00164                     }
00165                     chainHead = current->getNext();
00166                 } else {
00167                     if(currentCalled == current) {
00168                         currentCalled = previous;
00169                     }
00170                     previous->chainAsNext(current->getNext());
00171                 }
00172                 delete current;
00173                 return true;
00174             }
00175 
00176             previous = current;
00177             current = current->getNext();
00178         }
00179 
00180         return false;
00181     }
00182 
00183     /**
00184      * Remove all functions registered in the chain.
00185      */
00186     void clear(void)
00187     {
00188         pFunctionPointerWithContext_t  fptr = chainHead;
00189         while (fptr) {
00190             pFunctionPointerWithContext_t  deadPtr = fptr;
00191             fptr = deadPtr->getNext();
00192             delete deadPtr;
00193         }
00194 
00195         chainHead = NULL;
00196     }
00197 
00198     /**
00199      * Check whether the callchain contains any callbacks.
00200      *
00201      * @return true if the callchain is not empty and false otherwise.
00202      */
00203     bool hasCallbacksAttached(void) const
00204     {
00205         return (chainHead != NULL);
00206     }
00207 
00208     /**
00209      * Call sequentially each member of the chain.
00210      *
00211      * @param[in] context Parameter to pass to the functions called.
00212      */
00213     void call(ContextType context)
00214     {
00215         ((const CallChainOfFunctionPointersWithContext*) this)->call(context);
00216     }
00217 
00218     /**
00219      * Call sequentially each member of the chain.
00220      *
00221      * @param[in] context Parameter to pass to the functions called.
00222      */
00223     void call(ContextType context) const
00224     {
00225         currentCalled = chainHead;
00226 
00227         while(currentCalled) {
00228             currentCalled->call(context);
00229             // if this was the head and the call removed the head
00230             if(currentCalled == NULL) {
00231                 currentCalled = chainHead;
00232             } else {
00233                 currentCalled = currentCalled->getNext();
00234             }
00235         }
00236     }
00237 
00238     /**
00239      * Call sequentially each member of the chain.
00240      *
00241      * @param[in] context Parameter to pass to the functions called.
00242      *
00243      * @code
00244      *
00245      * void first(bool);
00246      * void second(bool);
00247      *
00248      * CallChainOfFunctionPointerWithContext<bool> foo;
00249      *
00250      * foo.attach(first);
00251      * foo.attach(second);
00252      *
00253      * // call the callchain like a function
00254      * foo(true);
00255      *
00256      * @endcode
00257      */
00258     void operator()(ContextType context) const
00259     {
00260         call(context);
00261     }
00262 
00263     /**
00264      * Test if the callchain is empty or not.
00265      *
00266      * @return true if the callchain is not empty and false otherwise.
00267      *
00268      * @note used by SafeBool to offer a safe boolean conversion.
00269      *
00270      * @code
00271      * CallChainOfFunctionPointersWithContext<void *> chain;
00272      *
00273      * if (!chain) {
00274      *   // Do something if the chain is empty.
00275      * }
00276      *
00277      * if (chain) {
00278      *   // Do something if the chain is not empty.
00279      * }
00280      * @endcode
00281      *
00282      */
00283     bool toBool() const
00284     {
00285         return chainHead != NULL;
00286     }
00287 
00288 private:
00289     /**
00290      * Add a callback to the head of the callchain.
00291      *
00292      * @return A pointer to the head of the callchain.
00293      */
00294     pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf)
00295     {
00296         if (chainHead == NULL) {
00297             chainHead = pf;
00298         } else {
00299             pf->chainAsNext(chainHead);
00300             chainHead = pf;
00301         }
00302 
00303         return chainHead;
00304     }
00305 
00306 private:
00307     /**
00308      * Pointer to the first callback of the callchain or NULL if the callchain
00309      * is empty.
00310      */
00311     pFunctionPointerWithContext_t chainHead;
00312 
00313     /**
00314      * Pointer to the function being called.
00315      *
00316      * It is used to maintain the data structure integrity if a function is
00317      * removed during the call() operation.
00318      *
00319      * @note It has to be mutable to accomodate the const version of call(). The
00320      * iterator doesn't leak outside the object; therefore, it remains seen as
00321      * const from an external standpoint.
00322      */
00323     mutable pFunctionPointerWithContext_t currentCalled;
00324 
00325 
00326     /* Disallow copy constructor and assignment operators. */
00327 private:
00328     CallChainOfFunctionPointersWithContext(
00329         const CallChainOfFunctionPointersWithContext&
00330     );
00331     CallChainOfFunctionPointersWithContext &operator=(
00332         const CallChainOfFunctionPointersWithContext&
00333     );
00334 };
00335 
00336 /**
00337  * @}
00338  * @}
00339  */
00340 
00341 #endif