20
20
#include < string.h>
21
21
#include " SafeBool.h"
22
22
23
- /* * A class for storing and calling a pointer to a static or member void function
24
- * that takes a context.
23
+ /* *
24
+ * @file
25
+ * @addtogroup ble
26
+ * @{
27
+ * @addtogroup common
28
+ * @{
29
+ */
30
+
31
+ /* *
32
+ * Function like object adapter over freestanding and member functions.
33
+ *
34
+ * Freestanding and member functions are two very distinct types in C++, one is
35
+ * not convertible into the other and the call syntax between those two is very
36
+ * different even if conceptually they are very similar: Both primitives can be
37
+ * copied, called and produce a result.
38
+ *
39
+ * To solve incompatibilities this class addapt freestanding and member function
40
+ * to a common interface. The interface chosen is similar to the freestanding
41
+ * function pointers interface:
42
+ * - Copyable
43
+ * - Nullable
44
+ * - Callable .
45
+ *
46
+ * This class also offers a mechanism to chain other instances to it. When an
47
+ * instance is called, all the instances being part of the chain are called.
48
+ *
49
+ * @important freestanding or member function adapted must accept a single
50
+ * argument and this argument shall be a pointer to ContextType. Adapted
51
+ * primitives shall not return anything.
52
+ *
53
+ * @tparam ContextType Type of the argument pointee.
25
54
*/
26
55
template <typename ContextType>
27
56
class FunctionPointerWithContext : public SafeBool <FunctionPointerWithContext<ContextType> > {
@@ -30,111 +59,201 @@ class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<Co
30
59
typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t;
31
60
typedef void (*pvoidfcontext_t )(ContextType context);
32
61
33
- /* * Create a FunctionPointerWithContext, attaching a static function.
62
+ /* *
63
+ * Create a FunctionPointerWithContext from a pointer to a freestanding
64
+ * function.
34
65
*
35
- * @param function The void static function to attach (default is none) .
66
+ * @param[in] function The freestanding function to attach.
36
67
*/
37
68
FunctionPointerWithContext (void (*function)(ContextType context) = NULL ) :
38
- _memberFunctionAndPointer (), _caller(NULL ), _next(NULL ) {
69
+ _memberFunctionAndPointer (), _caller(NULL ), _next(NULL )
70
+ {
39
71
attach (function);
40
72
}
41
73
42
- /* * Create a FunctionPointerWithContext, attaching a member function.
74
+ /* *
75
+ * Create a FunctionPointerWithContext from a pointer to member function
76
+ * and the instance which shall be used to call it.
43
77
*
44
- * @param object The object pointer to invoke the member function on (the "this" pointer).
45
- * @param function The address of the void member function to attach.
78
+ * @param[in] object Pointer to the instance which will be used to invoke @p
79
+ * member.
80
+ * @param[in] Pointer to the member function to adapt.
46
81
*/
47
82
template <typename T>
48
83
FunctionPointerWithContext (T *object, void (T::*member)(ContextType context)) :
49
- _memberFunctionAndPointer (), _caller(NULL ), _next(NULL ) {
84
+ _memberFunctionAndPointer (), _caller(NULL ), _next(NULL )
85
+ {
50
86
attach (object, member);
51
87
}
52
88
53
- FunctionPointerWithContext (const FunctionPointerWithContext& that) :
54
- _memberFunctionAndPointer (that._memberFunctionAndPointer), _caller(that._caller), _next(NULL ) {
89
+ /* *
90
+ * Copy construction.
91
+ *
92
+ * @param[in] that The FunctionPointerWithContext instance used to create
93
+ * this.
94
+ */
95
+ FunctionPointerWithContext (const FunctionPointerWithContext &that) :
96
+ _memberFunctionAndPointer (that._memberFunctionAndPointer),
97
+ _caller (that._caller), _next(NULL ) {
55
98
}
56
99
57
- FunctionPointerWithContext& operator =(const FunctionPointerWithContext& that) {
100
+ /* *
101
+ * Copy assignment.
102
+ *
103
+ * @param[in] that The FunctionPointerWithContext instance copied into this.
104
+ */
105
+ FunctionPointerWithContext &operator =(const FunctionPointerWithContext &that)
106
+ {
58
107
_memberFunctionAndPointer = that._memberFunctionAndPointer ;
59
- _caller = that._caller ;
108
+ _caller = that._caller ;
60
109
_next = NULL ;
61
110
return *this ;
62
111
}
63
112
64
- /* * Attach a static function.
113
+ /* *
114
+ * Adapt a freestanding function.
115
+ *
116
+ * Previous content adapted is discarded while it is replace by @p function.
65
117
*
66
- * @param function The void static function to attach (default is none).
118
+ * @note This function is equivalent to a call to the copy assignment
119
+ * operator.
120
+ *
121
+ * @param[in] function The freestanding function to attach.
67
122
*/
68
- void attach (void (*function)(ContextType context) = NULL) {
123
+ void attach (void (*function)(ContextType context) = NULL)
124
+ {
69
125
_function = function;
70
126
_caller = functioncaller;
71
127
}
72
128
73
- /* * Attach a member function.
129
+ /* *
130
+ * Adapt a pointer to member function and the instance to use to call it.
74
131
*
75
- * @param object The object pointer to invoke the member function on (the "this" pointer).
76
- * @param function The address of the void member function to attach.
132
+ * Previous content adapted is discarded while it is replace by the
133
+ * adaptation of the pair @p object and @p member.
134
+ *
135
+ * @note This function is equivalent to a call to the copy assignment
136
+ * operator.
137
+ *
138
+ * @param[in] object Pointer to the instance used to invoke @p member.
139
+ * @param[in] function Pointer to the member function to adapt.
77
140
*/
78
141
template <typename T>
79
- void attach (T *object, void (T::*member)(ContextType context)) {
142
+ void attach (T *object, void (T::*member)(ContextType context))
143
+ {
80
144
_memberFunctionAndPointer._object = static_cast <void *>(object);
81
- memcpy (_memberFunctionAndPointer._memberFunction , (char *) &member, sizeof (member));
145
+ memcpy (
146
+ _memberFunctionAndPointer._memberFunction ,
147
+ (char *) &member,
148
+ sizeof (member)
149
+ );
82
150
_caller = &FunctionPointerWithContext::membercaller<T>;
83
151
}
84
152
85
- /* * Call the attached static or member function; if there are chained
86
- * FunctionPointers their callbacks are invoked as well.
87
- * @Note: All chained callbacks stack up, so hopefully there won't be too
88
- * many FunctionPointers in a chain. */
89
- void call (ContextType context) const {
153
+ /* *
154
+ * Call the adapted function and functions chained to the instance.
155
+ *
156
+ * @param[in] context parameter to pass to chain of adapted functions.
157
+ */
158
+ void call (ContextType context) const
159
+ {
90
160
_caller (this , context);
91
161
}
92
162
93
163
/* *
94
- * @brief Same as above
164
+ * Call the adapted function and functions chained to the instance.
165
+ *
166
+ * @param[in] context parameter to pass to chain of adapted functions.
95
167
*/
96
- void operator ()(ContextType context) const {
97
- call (context);
168
+ void call (ContextType context)
169
+ {
170
+ ((const FunctionPointerWithContext*) this )->call (context);
98
171
}
99
172
100
- /* * Same as above, workaround for mbed os FunctionPointer implementation. */
101
- void call (ContextType context) {
102
- ((const FunctionPointerWithContext*) this )->call (context);
173
+ /* *
174
+ * Call the adapted function and functions chained to the instance.
175
+ *
176
+ * @param[in] context parameter to pass to chain of adapted functions.
177
+ */
178
+ void operator ()(ContextType context) const
179
+ {
180
+ call (context);
103
181
}
104
182
105
183
typedef void (FunctionPointerWithContext::*bool_type)() const ;
106
184
107
- /* *
108
- * implementation of safe bool operator
185
+ /* *
186
+ * Indicate if a callable object is being adapted.
187
+ *
188
+ * @note implementation of safe bool operator
189
+ *
190
+ * @return true if the content of the instance can be invoked and false
191
+ * otherwise.
109
192
*/
110
- bool toBool () const {
193
+ bool toBool () const
194
+ {
111
195
return (_function || _memberFunctionAndPointer._object );
112
196
}
113
197
114
198
/* *
115
- * Set up an external FunctionPointer as a next in the chain of related
116
- * callbacks. Invoking call() on the head FunctionPointer will invoke all
199
+ * Set a FunctionPointer instance as the next element in the chain of
200
+ * callable objects.
201
+ *
202
+ * @note Invoking call() on the head FunctionPointer will invoke all
117
203
* chained callbacks.
118
204
*
119
- * Refer to 'CallChain' as an alternative.
205
+ * @note Refer to CallChainOfFunctionPointerWithContext as an alternative.
206
+ *
207
+ * @param next The instance to set as the next element in the chain of
208
+ * callable objects.
120
209
*/
121
- void chainAsNext (pFunctionPointerWithContext_t next) {
210
+ void chainAsNext (pFunctionPointerWithContext_t next)
211
+ {
122
212
_next = next;
123
213
}
124
214
125
- pFunctionPointerWithContext_t getNext (void ) const {
215
+ /* *
216
+ * Access the next element in the call chain.
217
+ *
218
+ * If there is no next element in the chain, this function returns NULL.
219
+ *
220
+ * @return A pointer to the next FunctionPointerWithContext instance in the
221
+ * chain.
222
+ */
223
+ pFunctionPointerWithContext_t getNext (void ) const
224
+ {
126
225
return _next;
127
226
}
128
227
129
- pvoidfcontext_t get_function () const {
228
+ /* *
229
+ * Access the next element in the call chain.
230
+ *
231
+ * If there is no next element in the chain, this function returns NULL.
232
+ *
233
+ * @return A pointer to the next FunctionPointerWithContext instance in the
234
+ * chain.
235
+ */
236
+ pvoidfcontext_t get_function () const
237
+ {
130
238
return (pvoidfcontext_t )_function;
131
239
}
132
240
133
- friend bool operator ==(const FunctionPointerWithContext& lhs, const FunctionPointerWithContext& rhs) {
241
+ /* *
242
+ * Equal to operator between two FunctionPointerWithContext instances.
243
+ *
244
+ * @param[in] lhs Left hand side of the expression.
245
+ * @param[in] rhs Right hand side of the expression.
246
+ *
247
+ * @return true if lhs and rhs adapt the same object and false otherwise.
248
+ */
249
+ friend bool operator ==(
250
+ const FunctionPointerWithContext &lhs,
251
+ const FunctionPointerWithContext &rhs
252
+ ) {
134
253
return rhs._caller == lhs._caller &&
135
254
memcmp (
136
- &rhs._memberFunctionAndPointer ,
137
- &lhs._memberFunctionAndPointer ,
255
+ &rhs._memberFunctionAndPointer ,
256
+ &lhs._memberFunctionAndPointer ,
138
257
sizeof (rhs._memberFunctionAndPointer )
139
258
) == 0 ;
140
259
}
@@ -191,22 +310,53 @@ class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<Co
191
310
};
192
311
193
312
/* *
194
- * @brief Create a new FunctionPointerWithContext which bind an instance and a
195
- * a member function together.
196
- * @details This little helper is a just here to eliminate the need to write the
197
- * FunctionPointerWithContext type each time you want to create one by kicking
198
- * automatic type deduction of function templates. With this function, it is easy
199
- * to write only one entry point for functions which expect a FunctionPointer
200
- * in parameters.
201
- *
202
- * @param object to bound with member function
203
- * @param member The member function called
204
- * @return a new FunctionPointerWithContext
313
+ * Factory of adapted member function pointers.
314
+ *
315
+ * This factory eliminate the need to invoke the qualified constructor of
316
+ * FunctionPointerWithContext by using automatic type deduction of function
317
+ * templates
318
+ *
319
+ * @code
320
+ *
321
+ * struct ReadHandler {
322
+ * void on_data_read(const GattReadCallbackParams*);
323
+ * };
324
+ *
325
+ * ReadHandler read_handler;
326
+ *
327
+ * GattClient& client;
328
+ *
329
+ * client.onDataRead(
330
+ * makeFunctionPointer(&read_handler, &ReadHandler::on_data_read)
331
+ * );
332
+ *
333
+ * // instead of
334
+ *
335
+ * client.onDataRead(
336
+ * FunctionPointerWithContext<const GattReadCallbackParams*>(
337
+ * &read_handler,
338
+ * &ReadHandler::on_data_read
339
+ * )
340
+ * );
341
+ * @endcode
342
+ *
343
+ *
344
+ * @param[in] object Instance to bound with @p member.
345
+ * @param member The member being adapted.
346
+ *
347
+ * @return Adaptation of the parameters in a FunctionPointerWithContext instance.
205
348
*/
206
349
template <typename T, typename ContextType>
207
- FunctionPointerWithContext<ContextType> makeFunctionPointer (T *object, void (T::*member)(ContextType context))
208
- {
350
+ FunctionPointerWithContext<ContextType> makeFunctionPointer (
351
+ T *object,
352
+ void (T::*member)(ContextType context)
353
+ ) {
209
354
return FunctionPointerWithContext<ContextType>(object, member);
210
355
}
211
356
357
+ /* *
358
+ * @}
359
+ * @}
360
+ */
361
+
212
362
#endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
0 commit comments