40
\defgroup CBDATAAPI Callback Data Allocator API
43
* Squid's extensive use of callback functions makes it very
44
* susceptible to memory access errors. To address this all callback
45
* functions make use of a construct called cbdata. This allows
46
* functions doing callbacks to verify that the caller is still
47
* valid before making the callback.
49
\note cbdata is intended for callback data and is tailored specifically
50
* to make callbacks less dangerous leaving as few windows of errors as
51
* possible. It is not suitable or intended as a generic RefCount
54
\todo CODE: make cbdata a template or class-inheritance system instead of Macros.
56
\section Examples Examples
58
* Here you can find some examples on how to use cbdata, and why.
60
\subsection AsyncOpWithoutCBDATA Asynchronous operation without cbdata, showing why cbdata is needed
62
* For a asyncronous operation with callback functions, the normal
63
* sequence of events in programs NOT using cbdata is as follows:
67
type_of_data our_data;
69
our_data = malloc(...);
71
// Initiate a asyncronous operation, with our_data as callback_data
72
fooOperationStart(bar, callback_func, our_data);
74
// The asyncronous operation completes and makes the callback
75
callback_func(callback_data, ....);
76
// Some time later we clean up our data
81
* However, things become more interesting if we want or need
82
* to free the callback_data, or otherwise cancel the callback,
83
* before the operation completes. In constructs like this you
84
* can quite easily end up with having the memory referenced
85
* pointed to by callback_data freed before the callback is invoked
86
* causing a program failure or memory corruption:
90
type_of_data our_data;
92
our_data = malloc(...);
94
// Initiate a asyncronous operation, with our_data as callback_data
95
fooOperationStart(bar, callback_func, our_data);
97
// ouch, something bad happened elsewhere.. try to cleanup
98
// but the programmer forgot there is a callback pending from
99
// fooOperationsStart() (an easy thing to forget when writing code
100
// to deal with errors, especially if there may be many different
101
// pending operation)
104
// The asyncronous operation completes and makes the callback
105
callback_func(callback_data, ....);
106
// CRASH, the memory pointer to by callback_data is no longer valid
107
// at the time of the callback
110
\subsection AsyncOpWithCBDATA Asyncronous operation with cbdata
113
* The callback data allocator lets us do this in a uniform and
114
* safe manner. The callback data allocator is used to allocate,
115
* track and free memory pool objects used during callback
116
* operations. Allocated memory is locked while the asyncronous
117
* operation executes elsewhere, and is freed when the operation
118
* completes. The normal sequence of events is:
122
type_of_data our_data;
124
our_data = cbdataAlloc(type_of_data);
126
// Initiate a asyncronous operation, with our_data as callback_data
127
fooOperationStart(..., callback_func, our_data);
130
void *local_pointer = cbdataReference(callback_data);
132
// The asyncronous operation completes and makes the callback
134
if (cbdataReferenceValidDone(local_pointer, &cbdata))
135
callback_func(...., cbdata);
137
cbdataFree(our_data);
140
\subsection AsynchronousOpCancelledByCBDATA Asynchronous operation cancelled by cbdata
143
* With this scheme, nothing bad happens if cbdataFree() gets called
144
* before fooOperantionComplete(...).
148
type_of_data our_data;
150
our_data = cbdataAlloc(type_of_data);
152
* Initiate a asyncronous operation, with our_data as callback_data
154
fooOperationStart(..., callback_func, our_data);
156
* do some stuff with it
158
void *local_pointer = cbdataReference(callback_data);
160
* something bad happened elsewhere.. cleanup
162
cbdataFree(our_data);
164
* The asyncronous operation completes and tries to make the callback
167
if (cbdataReferenceValidDone(local_pointer, &cbdata))
170
* won't be called, as the data is no longer valid
172
callback_func(...., cbdata);
177
* In this case, when cbdataFree() is called before
178
* cbdataReferenceValidDone(), the callback_data gets marked as invalid.
179
* When the callback_data is invalid before executing the callback
180
* function, cbdataReferenceValidDone() will return 0 and
181
* callback_func is never executed.
183
\subsection AddingCBDATAType Adding a new cbdata registered type
186
* To add new module specific data types to the allocator one uses the
187
* macros CBDATA_TYPE() and CBDATA_INIT_TYPE(). These creates a local cbdata
188
* definition (file or block scope). Any cbdataAlloc() calls must be made
189
* within this scope. However, cbdataFree() might be called from anywhere.
192
* First the cbdata type needs to be defined in the module. This
193
* is usually done at file scope, but it can also be local to a
194
* function or block..
196
CBDATA_TYPE(type_of_data);
198
* Then in the code somewhere before the first allocation
199
* (can be called multiple times with only a minimal overhead)
201
CBDATA_INIT_TYPE(type_of_data);
203
* Or if a free function is associated with the data type. This
204
* function is responsible for cleaning up any dependencies etc
205
* referenced by the structure and is called on cbdataFree() or
206
* when the last reference is deleted by cbdataReferenceDone() /
207
* cbdataReferenceValidDone()
209
CBDATA_INIT_TYPE_FREECB(type_of_data, free_function);
212
\subsection AddingGlobalCBDATATypes Adding a new cbdata registered data type globally
215
* To add new global data types that can be allocated from anywhere
216
* within the code one have to add them to the cbdata_type enum in
217
* enums.h, and a corresponding CREATE_CBDATA() call in
218
* cbdata.c:cbdataInit(). Or alternatively add a CBDATA_GLOBAL_TYPE()
219
* definition to globals.h as shown below and use CBDATA_INIT_TYPE() at
220
* the appropriate location(s) as described above.
223
extern CBDATA_GLOBAL_TYPE(type_of_data); // CBDATA_UNDEF
41
229
* cbdata types. similar to the MEM_* types above, but managed
42
230
* in cbdata.c. A big difference is that these types are dynamically
43
231
* allocated. This list is only a list of predefined types. Other types
83
295
void operator delete (void *address) { \
84
296
if (address) cbdataInternalFreeDbg(address,__FILE__,__LINE__); \
298
void *toCbdata() { return this; } \
304
* Allocates a new entry of a registered CBDATA type.
88
306
#define cbdataAlloc(type) ((type *)cbdataInternalAlloc(CBDATA_##type))
311
* Frees a entry allocated by cbdataAlloc().
313
\note If there are active references to the entry then the entry
314
* will be freed with the last reference is removed. However,
315
* cbdataReferenceValid() will return false for those references.
89
317
#define cbdataFree(var) do {if (var) {cbdataInternalFree(var); var = NULL;}} while(0)
321
* Removes a reference created by cbdataReference() and checks
322
* it for validity. Meant to be used on the last dereference,
323
* usually to make a callback.
328
if (cbdataReferenceValidDone(reference, &cbdata)) != NULL)
329
callback(..., cbdata);
332
\param var The reference variable. Will be automatically cleared to NULL.
333
\param ptr A temporary pointer to the referenced data (if valid).
90
335
#define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValid((void **)&(var), (ptr))
93
* This needs to be defined LAST in teh class definition. It plays with private/public states in C++.
337
/// \ingroup CBDATAAPI
95
338
#define CBDATA_CLASS2(type) \
97
339
static cbdata_type CBDATA_##type; \
99
341
void *operator new(size_t size) { \
104
346
void operator delete (void *address) { \
105
347
if (address) cbdataInternalFree(address);\
349
void *toCbdata() { return this; } \
351
#endif /* !CBDATA_DEBUG */
356
* Creates a new reference to a cbdata entry. Used when you need to
357
* store a reference in another structure. The reference can later
358
* be verified for validity by cbdataReferenceValid().
361
* The reference variable is a pointer to the entry, in all
362
* aspects identical to the original pointer. But semantically it
363
* is quite different. It is best if the reference is thought of
364
* and handled as a "void *".
108
366
#define cbdataReference(var) (cbdataInternalLock(var), var)
370
* Removes a reference created by cbdataReference().
372
\param var The reference variable. Will be automatically cleared to NULL.
109
374
#define cbdataReferenceDone(var) do {if (var) {cbdataInternalUnlock(var); var = NULL;}} while(0)
376
/// \ingroup CBDATAAPI
110
377
#define CBDATA_CLASS(type) static cbdata_type CBDATA_##type
379
/// \ingroup CBDATAAPI
111
380
#define CBDATA_CLASS_INIT(type) cbdata_type type::CBDATA_##type = CBDATA_UNKNOWN
381
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type) cbdata_type namespace::type::CBDATA_##type = CBDATA_UNKNOWN
385
* Macro that defines a new cbdata datatype. Similar to a variable
386
* or struct definition. Scope is always local to the file/block
387
* where it is defined and all calls to cbdataAlloc() for this type
388
* must be within the same scope as the CBDATA_TYPE declaration.
389
* Allocated entries may be referenced or freed anywhere with no
390
* restrictions on scope.
112
392
#define CBDATA_TYPE(type) static cbdata_type CBDATA_##type = CBDATA_UNKNOWN
396
* Defines a global cbdata type that can be referenced anywhere in the code.
399
external CBDATA_GLOBAL_TYPE(datatype);
401
* Should be added to the module *.h header file.
404
CBDATA_GLOBAL_TYPE(datatype);
407
* Should be added to the module main *.cc file.
113
409
#define CBDATA_GLOBAL_TYPE(type) cbdata_type CBDATA_##type
414
* Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
417
* Alternative to CBDATA_INIT_TYPE_FREECB()
419
\param type Type being initialized
114
421
#define CBDATA_INIT_TYPE(type) (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), NULL)))
426
* Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
429
* Alternative to CBDATA_INIT_TYPE()
431
\param type Type being initialized
432
\param free_func The freehandler called when the last known reference to an allocated entry goes away.
115
434
#define CBDATA_INIT_TYPE_FREECB(type, free_func) (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), free_func)))
118
* use this when you need to pass callback data to a blocking
439
* A generic wrapper for passing objects through cbdata.
440
* Use this when you need to pass callback data to a blocking
119
441
* operation, but you don't want to/cannot have that pointer be cbdata itself.
122
443
class generic_cbdata
125
447
generic_cbdata(void * data) : data(data) {}
126
template<typename wrapped_type>void unwrap(wrapped_type **output)
128
*output = static_cast<wrapped_type *>(data);
131
/* the wrapped data - only public to allow the mild abuse of this facility
449
template<typename wrapped_type>void unwrap(wrapped_type **output) {
450
*output = static_cast<wrapped_type *>(data);
455
* The wrapped data - only public to allow the mild abuse of this facility
132
456
* done by store_swapout - it gives a wrapped StoreEntry to StoreIO as the
133
457
* object to be given to the callbacks. That needs to be fully cleaned up!
459
\todo CODE: make this a private field.
136
461
void *data; /* the wrapped data */
138
463
CBDATA_CLASS2(generic_cbdata);
143
466
#endif /* SQUID_CBDATA_H */