extend

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Mon Nov 02 09:09:05 2015 +0000
Revision:
848:47c11ba90ff4
Parent:
716:11b41f651697
Child:
849:0f5972e454b2
Synchronized with git rev 57c160c2
Author: Vincent Coubard
Reduce the memory size consummed by a FunctionPointerWithContext to 20
bytes (oryginally, it was 32 bytes !).
Enforce alignement constraints of the embedded pointer to member function.
Symplify and unify call mecanic, everything is delegated uniformally to the actual
implementation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 710:b2e1a2660ec2 1 /* mbed Microcontroller Library
rgrover1 710:b2e1a2660ec2 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 710:b2e1a2660ec2 3 *
rgrover1 710:b2e1a2660ec2 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 710:b2e1a2660ec2 5 * you may not use this file except in compliance with the License.
rgrover1 710:b2e1a2660ec2 6 * You may obtain a copy of the License at
rgrover1 710:b2e1a2660ec2 7 *
rgrover1 710:b2e1a2660ec2 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 710:b2e1a2660ec2 9 *
rgrover1 710:b2e1a2660ec2 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 710:b2e1a2660ec2 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 710:b2e1a2660ec2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 710:b2e1a2660ec2 13 * See the License for the specific language governing permissions and
rgrover1 710:b2e1a2660ec2 14 * limitations under the License.
rgrover1 710:b2e1a2660ec2 15 */
rgrover1 710:b2e1a2660ec2 16
rgrover1 710:b2e1a2660ec2 17 #ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
rgrover1 710:b2e1a2660ec2 18 #define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
rgrover1 710:b2e1a2660ec2 19
rgrover1 710:b2e1a2660ec2 20 #include <string.h>
rgrover1 710:b2e1a2660ec2 21
rgrover1 710:b2e1a2660ec2 22
rgrover1 848:47c11ba90ff4 23
rgrover1 710:b2e1a2660ec2 24 /** A class for storing and calling a pointer to a static or member void function
rgrover1 710:b2e1a2660ec2 25 * which takes a context.
rgrover1 710:b2e1a2660ec2 26 */
rgrover1 710:b2e1a2660ec2 27 template <typename ContextType>
rgrover1 710:b2e1a2660ec2 28 class FunctionPointerWithContext {
rgrover1 710:b2e1a2660ec2 29 public:
rgrover1 710:b2e1a2660ec2 30 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
rgrover1 710:b2e1a2660ec2 31 typedef void (*pvoidfcontext_t)(ContextType context);
rgrover1 710:b2e1a2660ec2 32
rgrover1 710:b2e1a2660ec2 33 /** Create a FunctionPointerWithContext, attaching a static function
rgrover1 710:b2e1a2660ec2 34 *
rgrover1 710:b2e1a2660ec2 35 * @param function The void static function to attach (default is none)
rgrover1 710:b2e1a2660ec2 36 */
rgrover1 710:b2e1a2660ec2 37 FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
rgrover1 848:47c11ba90ff4 38 _function(NULL), _caller(NULL), _next(NULL) {
rgrover1 710:b2e1a2660ec2 39 attach(function);
rgrover1 710:b2e1a2660ec2 40 }
rgrover1 710:b2e1a2660ec2 41
rgrover1 710:b2e1a2660ec2 42 /** Create a FunctionPointerWithContext, attaching a member function
rgrover1 710:b2e1a2660ec2 43 *
rgrover1 710:b2e1a2660ec2 44 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
rgrover1 710:b2e1a2660ec2 45 * @param function The address of the void member function to attach
rgrover1 710:b2e1a2660ec2 46 */
rgrover1 710:b2e1a2660ec2 47 template<typename T>
rgrover1 710:b2e1a2660ec2 48 FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
rgrover1 848:47c11ba90ff4 49 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
rgrover1 710:b2e1a2660ec2 50 attach(object, member);
rgrover1 710:b2e1a2660ec2 51 }
rgrover1 710:b2e1a2660ec2 52
rgrover1 710:b2e1a2660ec2 53 /** Attach a static function
rgrover1 710:b2e1a2660ec2 54 *
rgrover1 710:b2e1a2660ec2 55 * @param function The void static function to attach (default is none)
rgrover1 710:b2e1a2660ec2 56 */
rgrover1 710:b2e1a2660ec2 57 void attach(void (*function)(ContextType context) = NULL) {
rgrover1 710:b2e1a2660ec2 58 _function = function;
rgrover1 848:47c11ba90ff4 59 _caller = functioncaller;
rgrover1 710:b2e1a2660ec2 60 }
rgrover1 710:b2e1a2660ec2 61
rgrover1 710:b2e1a2660ec2 62 /** Attach a member function
rgrover1 710:b2e1a2660ec2 63 *
rgrover1 710:b2e1a2660ec2 64 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
rgrover1 710:b2e1a2660ec2 65 * @param function The address of the void member function to attach
rgrover1 710:b2e1a2660ec2 66 */
rgrover1 710:b2e1a2660ec2 67 template<typename T>
rgrover1 710:b2e1a2660ec2 68 void attach(T *object, void (T::*member)(ContextType context)) {
rgrover1 848:47c11ba90ff4 69 _memberFunctionAndPointer._object = static_cast<void *>(object);
rgrover1 848:47c11ba90ff4 70 memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member));
rgrover1 848:47c11ba90ff4 71 _caller = &FunctionPointerWithContext::membercaller<T>;
rgrover1 710:b2e1a2660ec2 72 }
rgrover1 710:b2e1a2660ec2 73
rgrover1 710:b2e1a2660ec2 74 /** Call the attached static or member function; and if there are chained
rgrover1 710:b2e1a2660ec2 75 * FunctionPointers their callbacks are invoked as well.
rgrover1 710:b2e1a2660ec2 76 * @Note: all chained callbacks stack up; so hopefully there won't be too
rgrover1 710:b2e1a2660ec2 77 * many FunctionPointers in a chain. */
rgrover1 710:b2e1a2660ec2 78 void call(ContextType context) {
rgrover1 848:47c11ba90ff4 79 _caller(this, context);
rgrover1 710:b2e1a2660ec2 80
rgrover1 710:b2e1a2660ec2 81 /* Propagate the call to next in the chain. */
rgrover1 710:b2e1a2660ec2 82 if (_next) {
rgrover1 710:b2e1a2660ec2 83 _next->call(context);
rgrover1 710:b2e1a2660ec2 84 }
rgrover1 710:b2e1a2660ec2 85 }
rgrover1 710:b2e1a2660ec2 86
rgrover1 710:b2e1a2660ec2 87 /**
rgrover1 710:b2e1a2660ec2 88 * Setup an external FunctionPointer as a next in the chain of related
rgrover1 710:b2e1a2660ec2 89 * callbacks. Invoking call() on the head FunctionPointer will invoke all
rgrover1 710:b2e1a2660ec2 90 * chained callbacks.
rgrover1 710:b2e1a2660ec2 91 *
rgrover1 710:b2e1a2660ec2 92 * Refer to 'CallChain' as an alternative.
rgrover1 710:b2e1a2660ec2 93 */
rgrover1 710:b2e1a2660ec2 94 void chainAsNext(pFunctionPointerWithContext_t next) {
rgrover1 710:b2e1a2660ec2 95 _next = next;
rgrover1 710:b2e1a2660ec2 96 }
rgrover1 710:b2e1a2660ec2 97
rgrover1 710:b2e1a2660ec2 98 pFunctionPointerWithContext_t getNext(void) const {
rgrover1 710:b2e1a2660ec2 99 return _next;
rgrover1 710:b2e1a2660ec2 100 }
rgrover1 710:b2e1a2660ec2 101
rgrover1 710:b2e1a2660ec2 102 pvoidfcontext_t get_function() const {
rgrover1 710:b2e1a2660ec2 103 return (pvoidfcontext_t)_function;
rgrover1 710:b2e1a2660ec2 104 }
rgrover1 710:b2e1a2660ec2 105
rgrover1 710:b2e1a2660ec2 106 private:
rgrover1 710:b2e1a2660ec2 107 template<typename T>
rgrover1 848:47c11ba90ff4 108 static void membercaller(FunctionPointerWithContext* self, ContextType context) {
rgrover1 848:47c11ba90ff4 109 if(self->_memberFunctionAndPointer._object) {
rgrover1 848:47c11ba90ff4 110 T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
rgrover1 848:47c11ba90ff4 111 void (T::*m)(ContextType);
rgrover1 848:47c11ba90ff4 112 memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m));
rgrover1 848:47c11ba90ff4 113 (o->*m)(context);
rgrover1 848:47c11ba90ff4 114 }
rgrover1 848:47c11ba90ff4 115 }
rgrover1 848:47c11ba90ff4 116
rgrover1 848:47c11ba90ff4 117 static void functioncaller(FunctionPointerWithContext* self, ContextType context) {
rgrover1 848:47c11ba90ff4 118 if(self->_function) {
rgrover1 848:47c11ba90ff4 119 self->_function(context);
rgrover1 848:47c11ba90ff4 120 }
rgrover1 710:b2e1a2660ec2 121 }
rgrover1 710:b2e1a2660ec2 122
rgrover1 848:47c11ba90ff4 123 struct MemberFunctionAndPtr {
rgrover1 848:47c11ba90ff4 124 /*
rgrover1 848:47c11ba90ff4 125 * forward declaration of a class and a member function to this class.
rgrover1 848:47c11ba90ff4 126 * Because the compiler doesnt know anything about the member function, it
rgrover1 848:47c11ba90ff4 127 * will always take the biggest size that a member function can take.
rgrover1 848:47c11ba90ff4 128 * This also guarantee that the proper alignement will be chosen
rgrover1 848:47c11ba90ff4 129 */
rgrover1 848:47c11ba90ff4 130 class UndefinedClass;
rgrover1 848:47c11ba90ff4 131 typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType);
rgrover1 848:47c11ba90ff4 132
rgrover1 848:47c11ba90ff4 133
rgrover1 848:47c11ba90ff4 134 void* _object;
rgrover1 848:47c11ba90ff4 135 union {
rgrover1 848:47c11ba90ff4 136 char _memberFunction[sizeof(UndefinedMemberFunction)];
rgrover1 848:47c11ba90ff4 137 UndefinedMemberFunction _allignement;
rgrover1 848:47c11ba90ff4 138 };
rgrover1 848:47c11ba90ff4 139 };
rgrover1 848:47c11ba90ff4 140
rgrover1 848:47c11ba90ff4 141
rgrover1 848:47c11ba90ff4 142
rgrover1 848:47c11ba90ff4 143 union {
rgrover1 848:47c11ba90ff4 144 void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */
rgrover1 848:47c11ba90ff4 145 /**
rgrover1 848:47c11ba90ff4 146 * object this pointer and pointer to member -
rgrover1 848:47c11ba90ff4 147 * _memberFunctionAndPointer._object will be NULL if none attached
rgrover1 848:47c11ba90ff4 148 */
rgrover1 848:47c11ba90ff4 149 MemberFunctionAndPtr _memberFunctionAndPointer;
rgrover1 848:47c11ba90ff4 150 };
rgrover1 848:47c11ba90ff4 151
rgrover1 848:47c11ba90ff4 152 void (*_caller)(FunctionPointerWithContext*, ContextType);
rgrover1 848:47c11ba90ff4 153
rgrover1 710:b2e1a2660ec2 154 pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this
rgrover1 710:b2e1a2660ec2 155 * allows chaining function pointers without requiring
rgrover1 710:b2e1a2660ec2 156 * external memory to manage the chain. Also refer to
rgrover1 710:b2e1a2660ec2 157 * 'CallChain' as an alternative. */
rgrover1 710:b2e1a2660ec2 158 };
rgrover1 710:b2e1a2660ec2 159
rgrover1 710:b2e1a2660ec2 160 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H