BLE_API for nRF51

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Mon Nov 02 09:09:05 2015 +0000
Revision:
851:802f445cc195
Parent:
850:32ff6e392630
Child:
852:f0de1349300c
Synchronized with git rev 129683bd
Author: Vincent Coubard
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.

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 851:802f445cc195 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 851:802f445cc195 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 851:802f445cc195 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 851:802f445cc195 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 851:802f445cc195 69 _memberFunctionAndPointer._object = static_cast<void *>(object);
rgrover1 851:802f445cc195 70 memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member));
rgrover1 851:802f445cc195 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 851:802f445cc195 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 851:802f445cc195 108 static void membercaller(pFunctionPointerWithContext_t self, ContextType context) {
rgrover1 851:802f445cc195 109 if (self->_memberFunctionAndPointer._object) {
rgrover1 851:802f445cc195 110 T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
rgrover1 851:802f445cc195 111 void (T::*m)(ContextType);
rgrover1 851:802f445cc195 112 memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m));
rgrover1 851:802f445cc195 113 (o->*m)(context);
rgrover1 851:802f445cc195 114 }
rgrover1 851:802f445cc195 115 }
rgrover1 851:802f445cc195 116
rgrover1 851:802f445cc195 117 static void functioncaller(pFunctionPointerWithContext_t self, ContextType context) {
rgrover1 851:802f445cc195 118 if (self->_function) {
rgrover1 851:802f445cc195 119 self->_function(context);
rgrover1 851:802f445cc195 120 }
rgrover1 710:b2e1a2660ec2 121 }
rgrover1 710:b2e1a2660ec2 122
rgrover1 851:802f445cc195 123 struct MemberFunctionAndPtr {
rgrover1 851:802f445cc195 124 /*
rgrover1 851:802f445cc195 125 * forward declaration of a class and a member function to this class.
rgrover1 851:802f445cc195 126 * Because the compiler doesn't know anything about the forwarded member
rgrover1 851:802f445cc195 127 * function, it will always use the biggest size and the biggest alignment
rgrover1 851:802f445cc195 128 * that a member function can take for objects of type UndefinedMemberFunction.
rgrover1 851:802f445cc195 129 */
rgrover1 851:802f445cc195 130 class UndefinedClass;
rgrover1 851:802f445cc195 131 typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType);
rgrover1 851:802f445cc195 132
rgrover1 851:802f445cc195 133 void* _object;
rgrover1 851:802f445cc195 134 union {
rgrover1 851:802f445cc195 135 char _memberFunction[sizeof(UndefinedMemberFunction)];
rgrover1 851:802f445cc195 136 UndefinedMemberFunction _alignment;
rgrover1 851:802f445cc195 137 };
rgrover1 851:802f445cc195 138 };
rgrover1 851:802f445cc195 139
rgrover1 851:802f445cc195 140 union {
rgrover1 851:802f445cc195 141 pvoidfcontext_t _function; /**< static function pointer - NULL if none attached */
rgrover1 851:802f445cc195 142 /**
rgrover1 851:802f445cc195 143 * object this pointer and pointer to member -
rgrover1 851:802f445cc195 144 * _memberFunctionAndPointer._object will be NULL if none attached
rgrover1 851:802f445cc195 145 */
rgrover1 851:802f445cc195 146 MemberFunctionAndPtr _memberFunctionAndPointer;
rgrover1 851:802f445cc195 147 };
rgrover1 851:802f445cc195 148
rgrover1 851:802f445cc195 149 void (*_caller)(FunctionPointerWithContext*, ContextType);
rgrover1 851:802f445cc195 150
rgrover1 710:b2e1a2660ec2 151 pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this
rgrover1 710:b2e1a2660ec2 152 * allows chaining function pointers without requiring
rgrover1 710:b2e1a2660ec2 153 * external memory to manage the chain. Also refer to
rgrover1 710:b2e1a2660ec2 154 * 'CallChain' as an alternative. */
rgrover1 710:b2e1a2660ec2 155 };
rgrover1 710:b2e1a2660ec2 156
rgrover1 710:b2e1a2660ec2 157 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H