]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cbdata.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / cbdata.h
CommitLineData
aa839030 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
aa839030 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
aa839030 7 */
8
9#ifndef SQUID_CBDATA_H
10#define SQUID_CBDATA_H
11
582c2af2 12#include "typedefs.h"
aa839030 13
63be0a78 14/**
15 \defgroup CBDATAAPI Callback Data Allocator API
16 \ingroup Components
17 \par
18 * Squid's extensive use of callback functions makes it very
19 * susceptible to memory access errors. To address this all callback
20 * functions make use of a construct called cbdata. This allows
21 * functions doing callbacks to verify that the caller is still
22 * valid before making the callback.
23 *
24 \note cbdata is intended for callback data and is tailored specifically
25 * to make callbacks less dangerous leaving as few windows of errors as
26 * possible. It is not suitable or intended as a generic RefCount
27 * memory allocator.
28 *
63be0a78 29 *
30 \section Examples Examples
31 \par
f53969cc 32 * Here you can find some examples on how to use cbdata, and why.
63be0a78 33 *
34 \subsection AsyncOpWithoutCBDATA Asynchronous operation without cbdata, showing why cbdata is needed
35 \par
f53969cc
SM
36 * For a asyncronous operation with callback functions, the normal
37 * sequence of events in programs NOT using cbdata is as follows:
63be0a78 38 *
39 \code
f53969cc
SM
40 // initialization
41 type_of_data our_data;
42 ...
43 our_data = malloc(...);
44 ...
45 // Initiate a asyncronous operation, with our_data as callback_data
46 fooOperationStart(bar, callback_func, our_data);
47 ...
48 // The asyncronous operation completes and makes the callback
49 callback_func(callback_data, ....);
50 // Some time later we clean up our data
51 free(our_data);
63be0a78 52 \endcode
53 *
54 \par
f53969cc
SM
55 * However, things become more interesting if we want or need
56 * to free the callback_data, or otherwise cancel the callback,
57 * before the operation completes. In constructs like this you
58 * can quite easily end up with having the memory referenced
59 * pointed to by callback_data freed before the callback is invoked
60 * causing a program failure or memory corruption:
63be0a78 61 *
62 \code
f53969cc
SM
63 // initialization
64 type_of_data our_data;
65 ...
66 our_data = malloc(...);
67 ...
68 // Initiate a asyncronous operation, with our_data as callback_data
69 fooOperationStart(bar, callback_func, our_data);
70 ...
71 // ouch, something bad happened elsewhere.. try to cleanup
72 // but the programmer forgot there is a callback pending from
73 // fooOperationsStart() (an easy thing to forget when writing code
74 // to deal with errors, especially if there may be many different
75 // pending operation)
76 free(our_data);
77 ...
78 // The asyncronous operation completes and makes the callback
79 callback_func(callback_data, ....);
80 // CRASH, the memory pointer to by callback_data is no longer valid
81 // at the time of the callback
63be0a78 82 \endcode
83 *
84 \subsection AsyncOpWithCBDATA Asyncronous operation with cbdata
85 *
86 \par
f53969cc
SM
87 * The callback data allocator lets us do this in a uniform and
88 * safe manner. The callback data allocator is used to allocate,
89 * track and free memory pool objects used during callback
90 * operations. Allocated memory is locked while the asyncronous
91 * operation executes elsewhere, and is freed when the operation
92 * completes. The normal sequence of events is:
63be0a78 93 *
94 \code
f53969cc
SM
95 // initialization
96 type_of_data our_data;
97 ...
98 our_data = cbdataAlloc(type_of_data);
99 ...
100 // Initiate a asyncronous operation, with our_data as callback_data
101 fooOperationStart(..., callback_func, our_data);
102 ...
103 // foo
104 void *local_pointer = cbdataReference(callback_data);
105 ....
106 // The asyncronous operation completes and makes the callback
107 void *cbdata;
108 if (cbdataReferenceValidDone(local_pointer, &cbdata))
109 callback_func(...., cbdata);
110 ...
111 cbdataFree(our_data);
63be0a78 112 \endcode
113 *
114 \subsection AsynchronousOpCancelledByCBDATA Asynchronous operation cancelled by cbdata
115 *
116 \par
f53969cc
SM
117 * With this scheme, nothing bad happens if cbdataFree() gets called
118 * before fooOperantionComplete(...).
63be0a78 119 *
f53969cc 120 \par Initalization
63be0a78 121 \code
f53969cc
SM
122 type_of_data our_data;
123 ...
124 our_data = cbdataAlloc(type_of_data);
63be0a78 125 \endcode
f53969cc 126 * Initiate a asyncronous operation, with our_data as callback_data
63be0a78 127 \code
f53969cc 128 fooOperationStart(..., callback_func, our_data);
63be0a78 129 \endcode
f53969cc 130 * do some stuff with it
63be0a78 131 \code
f53969cc 132 void *local_pointer = cbdataReference(callback_data);
63be0a78 133 \endcode
f53969cc 134 * something bad happened elsewhere.. cleanup
63be0a78 135 \code
f53969cc 136 cbdataFree(our_data);
63be0a78 137 \endcode
f53969cc 138 * The asyncronous operation completes and tries to make the callback
63be0a78 139 \code
f53969cc
SM
140 void *cbdata;
141 if (cbdataReferenceValidDone(local_pointer, &cbdata))
63be0a78 142 {
143 \endcode
f53969cc 144 * won't be called, as the data is no longer valid
63be0a78 145 \code
f53969cc
SM
146 callback_func(...., cbdata);
147 }
63be0a78 148 \endcode
149 *
150 \par
f53969cc
SM
151 * In this case, when cbdataFree() is called before
152 * cbdataReferenceValidDone(), the callback_data gets marked as invalid.
153 * When the callback_data is invalid before executing the callback
154 * function, cbdataReferenceValidDone() will return 0 and
155 * callback_func is never executed.
63be0a78 156 *
157 \subsection AddingCBDATAType Adding a new cbdata registered type
158 *
159 \par
f53969cc
SM
160 * To add new module specific data types to the allocator one uses the
161 * macro CBDATA_CLASS() in the class private section, and CBDATA_CLASS_INIT()
55bd8ddc
AJ
162 * or CBDATA_NAMESPACED_CLASS_INIT() in the .cc file.
163 * This creates new(), delete() and toCbdata() methods
f53969cc 164 * definition in class scope. Any allocate calls must be made with
55bd8ddc 165 * new() and destruction with delete(), they may be called from anywhere.
63be0a78 166 */
167
168/**
169 *\ingroup CBDATAAPI
e4f1ea43 170 * cbdata types. Similar to the MEM_* types, but managed in cbdata.cc
171 * A big difference is that cbdata types are dynamically allocated.
172 * Initially only UNKNOWN type is predefined. Other types are added runtime.
aa839030 173 */
e4f1ea43 174typedef int cbdata_type;
175static const cbdata_type CBDATA_UNKNOWN = 0;
aa839030 176
63be0a78 177/// \ingroup CBDATAAPI
8a648e8d 178void cbdataRegisterWithCacheManager(void);
63be0a78 179
63be0a78 180/**
63be0a78 181 * Allocates a new entry of a registered CBDATA type.
5c2f68b7 182 * \deprecated use CBDATA_CLASS() instead
63be0a78 183 */
5c2f68b7
AJ
184void *cbdataInternalAlloc(cbdata_type type, const char *, int);
185/// \deprecated use CBDATA_CLASS() instead
186#define cbdataAlloc(type) ((type *)cbdataInternalAlloc(CBDATA_##type,__FILE__,__LINE__))
63be0a78 187
188/**
5c2f68b7 189 * Frees a entry allocated by cbdataAlloc().
63be0a78 190 *
191 \note If there are active references to the entry then the entry
192 * will be freed with the last reference is removed. However,
193 * cbdataReferenceValid() will return false for those references.
5c2f68b7 194 * \deprecated use CBDATA_CLASS() instead
63be0a78 195 */
5c2f68b7
AJ
196void *cbdataInternalFree(void *p, const char *, int);
197/// \deprecated use CBDATA_CLASS() instead
f53969cc 198#define cbdataFree(var) do {if (var) {cbdataInternalFree(var,__FILE__,__LINE__); var = NULL;}} while(0)
5c2f68b7
AJ
199
200#if USE_CBDATA_DEBUG
201void cbdataInternalLockDbg(const void *p, const char *, int);
f53969cc 202#define cbdataInternalLock(a) cbdataInternalLockDbg(a,__FILE__,__LINE__)
5c2f68b7
AJ
203
204void cbdataInternalUnlockDbg(const void *p, const char *, int);
f53969cc 205#define cbdataInternalUnlock(a) cbdataInternalUnlockDbg(a,__FILE__,__LINE__)
5c2f68b7
AJ
206
207int cbdataInternalReferenceDoneValidDbg(void **p, void **tp, const char *, int);
208#define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValidDbg((void **)&(var), (ptr), __FILE__,__LINE__)
209
210#else
211void cbdataInternalLock(const void *p);
212void cbdataInternalUnlock(const void *p);
63be0a78 213
214/**
63be0a78 215 * Removes a reference created by cbdataReference() and checks
216 * it for validity. Meant to be used on the last dereference,
217 * usually to make a callback.
218 *
219 \code
220 void *cbdata;
221 ...
222 if (cbdataReferenceValidDone(reference, &cbdata)) != NULL)
223 callback(..., cbdata);
224 \endcode
225 *
f53969cc
SM
226 \param var The reference variable. Will be automatically cleared to NULL.
227 \param ptr A temporary pointer to the referenced data (if valid).
63be0a78 228 */
5c2f68b7 229int cbdataInternalReferenceDoneValid(void **p, void **tp);
aa839030 230#define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValid((void **)&(var), (ptr))
63be0a78 231
5c2f68b7
AJ
232#endif /* !CBDATA_DEBUG */
233
d2bf2f90 234/**
f53969cc 235 * \param p A cbdata entry reference pointer.
f54f527e 236 *
f53969cc
SM
237 * \retval 0 A reference is stale. The pointer refers to a entry freed by cbdataFree().
238 * \retval true The reference is valid and active.
d2bf2f90 239 */
5c2f68b7
AJ
240int cbdataReferenceValid(const void *p);
241
242/// \ingroup CBDATAAPI
243cbdata_type cbdataInternalAddType(cbdata_type type, const char *label, int size, FREE * free_func);
244
245/**
246 * This needs to be defined FIRST in the class definition.
247 * It plays with private/public states in C++.
248 */
f53969cc
SM
249#define CBDATA_CLASS(type) \
250 public: \
251 void *operator new(size_t size) { \
252 assert(size == sizeof(type)); \
253 if (!CBDATA_##type) \
d6f8a323 254 CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), NULL); \
f53969cc
SM
255 return (type *)cbdataInternalAlloc(CBDATA_##type,__FILE__,__LINE__); \
256 } \
257 void operator delete (void *address) { \
258 if (address) cbdataInternalFree(address,__FILE__,__LINE__);\
259 } \
5c2f68b7 260 void *toCbdata() { return this; } \
f53969cc
SM
261 private: \
262 static cbdata_type CBDATA_##type;
63be0a78 263
264/**
63be0a78 265 \par
266 * Creates a new reference to a cbdata entry. Used when you need to
267 * store a reference in another structure. The reference can later
268 * be verified for validity by cbdataReferenceValid().
269 *
270 \param var
271 * The reference variable is a pointer to the entry, in all
272 * aspects identical to the original pointer. But semantically it
273 * is quite different. It is best if the reference is thought of
274 * and handled as a "void *".
275 */
f53969cc 276#define cbdataReference(var) (cbdataInternalLock(var), var)
63be0a78 277
278/**
279 \ingroup CBDATAAPI
280 * Removes a reference created by cbdataReference().
281 *
f53969cc 282 \param var The reference variable. Will be automatically cleared to NULL.
63be0a78 283 */
aa839030 284#define cbdataReferenceDone(var) do {if (var) {cbdataInternalUnlock(var); var = NULL;}} while(0)
63be0a78 285
63be0a78 286/// \ingroup CBDATAAPI
aa839030 287#define CBDATA_CLASS_INIT(type) cbdata_type type::CBDATA_##type = CBDATA_UNKNOWN
99f1f996 288#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type) cbdata_type namespace::type::CBDATA_##type = CBDATA_UNKNOWN
63be0a78 289
290/**
63be0a78 291 * Macro that defines a new cbdata datatype. Similar to a variable
292 * or struct definition. Scope is always local to the file/block
293 * where it is defined and all calls to cbdataAlloc() for this type
294 * must be within the same scope as the CBDATA_TYPE declaration.
295 * Allocated entries may be referenced or freed anywhere with no
296 * restrictions on scope.
5c2f68b7 297 * \deprecated Use CBDATA_CLASS() instead
63be0a78 298 */
f53969cc 299#define CBDATA_TYPE(type) static cbdata_type CBDATA_##type = CBDATA_UNKNOWN
63be0a78 300
63be0a78 301/**
302 \ingroup CBDATAAPI
26ac0430 303 *
63be0a78 304 * Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
305 *
306 \par
b225f6b2 307 * Alternative to CBDATA_INIT_TYPE()
63be0a78 308 *
f53969cc
SM
309 \param type Type being initialized
310 \param free_func The freehandler called when the last known reference to an allocated entry goes away.
63be0a78 311 */
b225f6b2 312#define CBDATA_INIT_TYPE_FREECB(type, free_func) do { if (!CBDATA_##type) CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), free_func); } while (false)
63be0a78 313
314/**
63be0a78 315 * Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
316 *
317 \par
b225f6b2 318 * Alternative to CBDATA_INIT_TYPE_FREECB()
63be0a78 319 *
f53969cc 320 \param type Type being initialized
5c2f68b7
AJ
321 *
322 * \deprecated Use CBDATA_CLASS() instead
63be0a78 323 */
f53969cc 324#define CBDATA_INIT_TYPE(type) CBDATA_INIT_TYPE_FREECB(type, NULL)
aa839030 325
63be0a78 326/**
327 \ingroup CBDATA
328 *
329 * A generic wrapper for passing objects through cbdata.
330 * Use this when you need to pass callback data to a blocking
aa839030 331 * operation, but you don't want to/cannot have that pointer be cbdata itself.
332 */
aa839030 333class generic_cbdata
334{
5c2f68b7
AJ
335 CBDATA_CLASS(generic_cbdata);
336
26ac0430 337public:
63be0a78 338
18ec8500 339 generic_cbdata(void * aData) : data(aData) {}
63be0a78 340
26ac0430
AJ
341 template<typename wrapped_type>void unwrap(wrapped_type **output) {
342 *output = static_cast<wrapped_type *>(data);
343 delete this;
344 }
63be0a78 345
346 /**
347 * The wrapped data - only public to allow the mild abuse of this facility
aa839030 348 * done by store_swapout - it gives a wrapped StoreEntry to StoreIO as the
349 * object to be given to the callbacks. That needs to be fully cleaned up!
350 * - RBC 20060820
63be0a78 351 \todo CODE: make this a private field.
aa839030 352 */
353 void *data; /* the wrapped data */
aa839030 354};
355
aa839030 356#endif /* SQUID_CBDATA_H */
f53969cc 357