From 57c160c25ca2d457eaabce104bf55238756eac63 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 23 Oct 2015 15:59:53 +0100 Subject: [PATCH 1/3] 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. --- ble/FunctionPointerWithContext.h | 73 +++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/ble/FunctionPointerWithContext.h b/ble/FunctionPointerWithContext.h index c886bb3..ff76ee3 100644 --- a/ble/FunctionPointerWithContext.h +++ b/ble/FunctionPointerWithContext.h @@ -20,6 +20,7 @@ #include + /** A class for storing and calling a pointer to a static or member void function * which takes a context. */ @@ -34,7 +35,7 @@ public: * @param function The void static function to attach (default is none) */ FunctionPointerWithContext(void (*function)(ContextType context) = NULL) : - _function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) { + _function(NULL), _caller(NULL), _next(NULL) { attach(function); } @@ -45,7 +46,7 @@ public: */ template FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) : - _function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) { + _memberFunctionAndPointer(), _caller(NULL), _next(NULL) { attach(object, member); } @@ -55,6 +56,7 @@ public: */ void attach(void (*function)(ContextType context) = NULL) { _function = function; + _caller = functioncaller; } /** Attach a member function @@ -64,9 +66,9 @@ public: */ template void attach(T *object, void (T::*member)(ContextType context)) { - _object = static_cast(object); - memcpy(_member, (char *)&member, sizeof(member)); - _membercaller = &FunctionPointerWithContext::membercaller; + _memberFunctionAndPointer._object = static_cast(object); + memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member)); + _caller = &FunctionPointerWithContext::membercaller; } /** Call the attached static or member function; and if there are chained @@ -74,11 +76,7 @@ public: * @Note: all chained callbacks stack up; so hopefully there won't be too * many FunctionPointers in a chain. */ void call(ContextType context) { - if (_function) { - _function(context); - } else if (_object && _membercaller) { - _membercaller(_object, _member, context); - } + _caller(this, context); /* Propagate the call to next in the chain. */ if (_next) { @@ -107,19 +105,52 @@ public: private: template - static void membercaller(void *object, char *member, ContextType context) { - T *o = static_cast(object); - void (T::*m)(ContextType); - memcpy((char *)&m, member, sizeof(m)); - (o->*m)(context); + static void membercaller(FunctionPointerWithContext* self, ContextType context) { + if(self->_memberFunctionAndPointer._object) { + T *o = static_cast(self->_memberFunctionAndPointer._object); + void (T::*m)(ContextType); + memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); + (o->*m)(context); + } } - void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */ - void *_object; /**< object this pointer - NULL if none attached */ - char _member[16]; /**< raw member function pointer storage - converted back by - * registered _membercaller */ - void (*_membercaller)(void *, char *, ContextType); /**< registered membercaller function to convert back and call - * _member on _object passing the context. */ + static void functioncaller(FunctionPointerWithContext* self, ContextType context) { + if(self->_function) { + self->_function(context); + } + } + + struct MemberFunctionAndPtr { + /* + * forward declaration of a class and a member function to this class. + * Because the compiler doesnt know anything about the member function, it + * will always take the biggest size that a member function can take. + * This also guarantee that the proper alignement will be chosen + */ + class UndefinedClass; + typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); + + + void* _object; + union { + char _memberFunction[sizeof(UndefinedMemberFunction)]; + UndefinedMemberFunction _allignement; + }; + }; + + + + union { + void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */ + /** + * object this pointer and pointer to member - + * _memberFunctionAndPointer._object will be NULL if none attached + */ + MemberFunctionAndPtr _memberFunctionAndPointer; + }; + + void (*_caller)(FunctionPointerWithContext*, ContextType); + pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this * allows chaining function pointers without requiring * external memory to manage the chain. Also refer to From 8bad0486cd890aacc19681893afa5e4fd96eb63a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 23 Oct 2015 19:03:33 +0100 Subject: [PATCH 2/3] Remove unneeded blank lines. --- ble/FunctionPointerWithContext.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/ble/FunctionPointerWithContext.h b/ble/FunctionPointerWithContext.h index ff76ee3..5152c4b 100644 --- a/ble/FunctionPointerWithContext.h +++ b/ble/FunctionPointerWithContext.h @@ -130,7 +130,6 @@ private: class UndefinedClass; typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); - void* _object; union { char _memberFunction[sizeof(UndefinedMemberFunction)]; @@ -138,8 +137,6 @@ private: }; }; - - union { void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */ /** From 129683bdc03e6d259a2530d6250f8fdc206857b6 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 26 Oct 2015 10:44:21 +0000 Subject: [PATCH 3/3] Code and command cleanup: - add a space after if keyword - Use typedef types instead of direct declarations for pFunctionPointerWithContext_t and pvoidfcontext_t - Fix typos and enhance comment about how alignement and size requirements of the member function pointer are computed. --- ble/FunctionPointerWithContext.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ble/FunctionPointerWithContext.h b/ble/FunctionPointerWithContext.h index 5152c4b..41f8687 100644 --- a/ble/FunctionPointerWithContext.h +++ b/ble/FunctionPointerWithContext.h @@ -105,8 +105,8 @@ public: private: template - static void membercaller(FunctionPointerWithContext* self, ContextType context) { - if(self->_memberFunctionAndPointer._object) { + static void membercaller(pFunctionPointerWithContext_t self, ContextType context) { + if (self->_memberFunctionAndPointer._object) { T *o = static_cast(self->_memberFunctionAndPointer._object); void (T::*m)(ContextType); memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); @@ -114,8 +114,8 @@ private: } } - static void functioncaller(FunctionPointerWithContext* self, ContextType context) { - if(self->_function) { + static void functioncaller(pFunctionPointerWithContext_t self, ContextType context) { + if (self->_function) { self->_function(context); } } @@ -123,9 +123,9 @@ private: struct MemberFunctionAndPtr { /* * forward declaration of a class and a member function to this class. - * Because the compiler doesnt know anything about the member function, it - * will always take the biggest size that a member function can take. - * This also guarantee that the proper alignement will be chosen + * Because the compiler doesn't know anything about the forwarded member + * function, it will always use the biggest size and the biggest alignment + * that a member function can take for objects of type UndefinedMemberFunction. */ class UndefinedClass; typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); @@ -133,12 +133,12 @@ private: void* _object; union { char _memberFunction[sizeof(UndefinedMemberFunction)]; - UndefinedMemberFunction _allignement; + UndefinedMemberFunction _alignment; }; }; union { - void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */ + pvoidfcontext_t _function; /**< static function pointer - NULL if none attached */ /** * object this pointer and pointer to member - * _memberFunctionAndPointer._object will be NULL if none attached