]> git.ipfire.org Git - thirdparty/squid.git/blob - src/cbdata.h
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / cbdata.h
1 /*
2 * $Id$
3 *
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
32 */
33
34 #ifndef SQUID_CBDATA_H
35 #define SQUID_CBDATA_H
36
37 #include "squid-old.h"
38
39 /**
40 \defgroup CBDATAAPI Callback Data Allocator API
41 \ingroup Components
42 \par
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.
48 *
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
52 * memory allocator.
53 *
54 \todo CODE: make cbdata a template or class-inheritance system instead of Macros.
55 *
56 \section Examples Examples
57 \par
58 * Here you can find some examples on how to use cbdata, and why.
59 *
60 \subsection AsyncOpWithoutCBDATA Asynchronous operation without cbdata, showing why cbdata is needed
61 \par
62 * For a asyncronous operation with callback functions, the normal
63 * sequence of events in programs NOT using cbdata is as follows:
64 *
65 \code
66 // initialization
67 type_of_data our_data;
68 ...
69 our_data = malloc(...);
70 ...
71 // Initiate a asyncronous operation, with our_data as callback_data
72 fooOperationStart(bar, callback_func, our_data);
73 ...
74 // The asyncronous operation completes and makes the callback
75 callback_func(callback_data, ....);
76 // Some time later we clean up our data
77 free(our_data);
78 \endcode
79 *
80 \par
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:
87 *
88 \code
89 // initialization
90 type_of_data our_data;
91 ...
92 our_data = malloc(...);
93 ...
94 // Initiate a asyncronous operation, with our_data as callback_data
95 fooOperationStart(bar, callback_func, our_data);
96 ...
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)
102 free(our_data);
103 ...
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
108 \endcode
109 *
110 \subsection AsyncOpWithCBDATA Asyncronous operation with cbdata
111 *
112 \par
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:
119 *
120 \code
121 // initialization
122 type_of_data our_data;
123 ...
124 our_data = cbdataAlloc(type_of_data);
125 ...
126 // Initiate a asyncronous operation, with our_data as callback_data
127 fooOperationStart(..., callback_func, our_data);
128 ...
129 // foo
130 void *local_pointer = cbdataReference(callback_data);
131 ....
132 // The asyncronous operation completes and makes the callback
133 void *cbdata;
134 if (cbdataReferenceValidDone(local_pointer, &amp;cbdata))
135 callback_func(...., cbdata);
136 ...
137 cbdataFree(our_data);
138 \endcode
139 *
140 \subsection AsynchronousOpCancelledByCBDATA Asynchronous operation cancelled by cbdata
141 *
142 \par
143 * With this scheme, nothing bad happens if cbdataFree() gets called
144 * before fooOperantionComplete(...).
145 *
146 \par Initalization
147 \code
148 type_of_data our_data;
149 ...
150 our_data = cbdataAlloc(type_of_data);
151 \endcode
152 * Initiate a asyncronous operation, with our_data as callback_data
153 \code
154 fooOperationStart(..., callback_func, our_data);
155 \endcode
156 * do some stuff with it
157 \code
158 void *local_pointer = cbdataReference(callback_data);
159 \endcode
160 * something bad happened elsewhere.. cleanup
161 \code
162 cbdataFree(our_data);
163 \endcode
164 * The asyncronous operation completes and tries to make the callback
165 \code
166 void *cbdata;
167 if (cbdataReferenceValidDone(local_pointer, &amp;cbdata))
168 {
169 \endcode
170 * won't be called, as the data is no longer valid
171 \code
172 callback_func(...., cbdata);
173 }
174 \endcode
175 *
176 \par
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.
182 *
183 \subsection AddingCBDATAType Adding a new cbdata registered type
184 *
185 \par
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.
190 *
191 \par
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..
195 \code
196 CBDATA_TYPE(type_of_data);
197 \endcode
198 * Then in the code somewhere before the first allocation
199 * (can be called multiple times with only a minimal overhead)
200 \code
201 CBDATA_INIT_TYPE(type_of_data);
202 \endcode
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()
208 \code
209 CBDATA_INIT_TYPE_FREECB(type_of_data, free_function);
210 \endcode
211 *
212 \subsection AddingGlobalCBDATATypes Adding a new cbdata registered data type globally
213 *
214 \par
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.
221 *
222 \code
223 extern CBDATA_GLOBAL_TYPE(type_of_data); // CBDATA_UNDEF
224 \endcode
225 */
226
227 /**
228 *\ingroup CBDATAAPI
229 * cbdata types. similar to the MEM_* types above, but managed
230 * in cbdata.c. A big difference is that these types are dynamically
231 * allocated. This list is only a list of predefined types. Other types
232 * are added runtime
233 */
234 typedef enum {
235 CBDATA_UNKNOWN = 0
236 } cbdata_type;
237
238 /// \ingroup CBDATAAPI
239 extern void cbdataRegisterWithCacheManager(void);
240
241 #if USE_CBDATA_DEBUG
242 extern void *cbdataInternalAllocDbg(cbdata_type type, const char *, int);
243 extern void *cbdataInternalFreeDbg(void *p, const char *, int);
244 extern void cbdataInternalLockDbg(const void *p, const char *, int);
245 extern void cbdataInternalUnlockDbg(const void *p, const char *, int);
246 extern int cbdataInternalReferenceDoneValidDbg(void **p, void **tp, const char *, int);
247 #else
248
249 /// \ingroup CBDATAAPI
250 extern void *cbdataInternalAlloc(cbdata_type type);
251
252 /// \ingroup CBDATAAPI
253 extern void *cbdataInternalFree(void *p);
254
255 /// \ingroup CBDATAAPI
256 extern void cbdataInternalLock(const void *p);
257
258 /// \ingroup CBDATAAPI
259 extern void cbdataInternalUnlock(const void *p);
260
261 /// \ingroup CBDATAAPI
262 extern int cbdataInternalReferenceDoneValid(void **p, void **tp);
263
264 #endif /* !CBDATA_DEBUG */
265
266 /**
267 \ingroup CBDATAAPI
268 *
269 \param p A cbdata entry reference pointer.
270 *
271 \retval 0 A reference is stale. The pointer refers to a entry freed by cbdataFree().
272 \retval true The reference is valid and active.
273 */
274 extern int cbdataReferenceValid(const void *p);
275
276 /// \ingroup CBDATAAPI
277 extern cbdata_type cbdataInternalAddType(cbdata_type type, const char *label, int size, FREE * free_func);
278
279
280 /* cbdata macros */
281 #if USE_CBDATA_DEBUG
282 #define cbdataAlloc(type) ((type *)cbdataInternalAllocDbg(CBDATA_##type,__FILE__,__LINE__))
283 #define cbdataFree(var) do {if (var) {cbdataInternalFreeDbg(var,__FILE__,__LINE__); var = NULL;}} while(0)
284 #define cbdataInternalLock(a) cbdataInternalLockDbg(a,__FILE__,__LINE__)
285 #define cbdataInternalUnlock(a) cbdataInternalUnlockDbg(a,__FILE__,__LINE__)
286 #define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValidDbg((void **)&(var), (ptr), __FILE__,__LINE__)
287 #define CBDATA_CLASS2(type) \
288 private: \
289 static cbdata_type CBDATA_##type; \
290 public: \
291 void *operator new(size_t size) { \
292 assert(size == sizeof(type)); \
293 (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), NULL))); \
294 return cbdataInternalAllocDbg(CBDATA_##type,__FILE__,__LINE__); \
295 } \
296 void operator delete (void *address) { \
297 if (address) cbdataInternalFreeDbg(address,__FILE__,__LINE__); \
298 } \
299 void *toCbdata() { return this; }
300 #else /* USE_CBDATA_DEBUG */
301
302 /**
303 \ingroup CBDATAAPI
304 * Allocates a new entry of a registered CBDATA type.
305 */
306 #define cbdataAlloc(type) ((type *)cbdataInternalAlloc(CBDATA_##type))
307
308 /**
309 \ingroup CBDATAAPI
310 \par
311 * Frees a entry allocated by cbdataAlloc().
312 *
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.
316 */
317 #define cbdataFree(var) do {if (var) {cbdataInternalFree(var); var = NULL;}} while(0)
318
319 /**
320 \ingroup CBDATAAPI
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.
324 *
325 \code
326 void *cbdata;
327 ...
328 if (cbdataReferenceValidDone(reference, &cbdata)) != NULL)
329 callback(..., cbdata);
330 \endcode
331 *
332 \param var The reference variable. Will be automatically cleared to NULL.
333 \param ptr A temporary pointer to the referenced data (if valid).
334 */
335 #define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValid((void **)&(var), (ptr))
336
337 /**
338 * \ingroup CBDATAAPI
339 *
340 * This needs to be defined LAST in teh class definition. It plays with private/public states in C++.
341 */
342 #define CBDATA_CLASS2(type) \
343 private: \
344 static cbdata_type CBDATA_##type; \
345 public: \
346 void *operator new(size_t size) { \
347 assert(size == sizeof(type)); \
348 (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), NULL))); \
349 return (type *)cbdataInternalAlloc(CBDATA_##type); \
350 } \
351 void operator delete (void *address) { \
352 if (address) cbdataInternalFree(address);\
353 } \
354 void *toCbdata() { return this; }
355 #endif /* !CBDATA_DEBUG */
356
357 /**
358 \ingroup CBDATAAPI
359 \par
360 * Creates a new reference to a cbdata entry. Used when you need to
361 * store a reference in another structure. The reference can later
362 * be verified for validity by cbdataReferenceValid().
363 *
364 \param var
365 * The reference variable is a pointer to the entry, in all
366 * aspects identical to the original pointer. But semantically it
367 * is quite different. It is best if the reference is thought of
368 * and handled as a "void *".
369 */
370 #define cbdataReference(var) (cbdataInternalLock(var), var)
371
372 /**
373 \ingroup CBDATAAPI
374 * Removes a reference created by cbdataReference().
375 *
376 \param var The reference variable. Will be automatically cleared to NULL.
377 */
378 #define cbdataReferenceDone(var) do {if (var) {cbdataInternalUnlock(var); var = NULL;}} while(0)
379
380 /// \ingroup CBDATAAPI
381 #define CBDATA_CLASS(type) static cbdata_type CBDATA_##type
382
383 /// \ingroup CBDATAAPI
384 #define CBDATA_CLASS_INIT(type) cbdata_type type::CBDATA_##type = CBDATA_UNKNOWN
385 #define CBDATA_NAMESPACED_CLASS_INIT(namespace, type) cbdata_type namespace::type::CBDATA_##type = CBDATA_UNKNOWN
386
387 /**
388 \ingroup CBDATAAPI
389 * Macro that defines a new cbdata datatype. Similar to a variable
390 * or struct definition. Scope is always local to the file/block
391 * where it is defined and all calls to cbdataAlloc() for this type
392 * must be within the same scope as the CBDATA_TYPE declaration.
393 * Allocated entries may be referenced or freed anywhere with no
394 * restrictions on scope.
395 */
396 #define CBDATA_TYPE(type) static cbdata_type CBDATA_##type = CBDATA_UNKNOWN
397
398 /**
399 \ingroup CBDATAAPI
400 * Defines a global cbdata type that can be referenced anywhere in the code.
401 *
402 \code
403 external CBDATA_GLOBAL_TYPE(datatype);
404 \endcode
405 * Should be added to the module *.h header file.
406 *
407 \code
408 CBDATA_GLOBAL_TYPE(datatype);
409 \endcode
410 *
411 * Should be added to the module main *.cc file.
412 */
413 #define CBDATA_GLOBAL_TYPE(type) cbdata_type CBDATA_##type
414
415 /**
416 \ingroup CBDATAAPI
417 *
418 * Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
419 *
420 \par
421 * Alternative to CBDATA_INIT_TYPE_FREECB()
422 *
423 \param type Type being initialized
424 */
425 #define CBDATA_INIT_TYPE(type) (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), NULL)))
426
427 /**
428 \ingroup CBDATAAPI
429 *
430 * Initializes the cbdatatype. Must be called prior to the first use of cbdataAlloc() for the type.
431 *
432 \par
433 * Alternative to CBDATA_INIT_TYPE()
434 *
435 \param type Type being initialized
436 \param free_func The freehandler called when the last known reference to an allocated entry goes away.
437 */
438 #define CBDATA_INIT_TYPE_FREECB(type, free_func) (CBDATA_##type ? CBDATA_UNKNOWN : (CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type), free_func)))
439
440 /**
441 \ingroup CBDATA
442 *
443 * A generic wrapper for passing objects through cbdata.
444 * Use this when you need to pass callback data to a blocking
445 * operation, but you don't want to/cannot have that pointer be cbdata itself.
446 */
447 class generic_cbdata
448 {
449 public:
450
451 generic_cbdata(void * aData) : data(aData) {}
452
453 template<typename wrapped_type>void unwrap(wrapped_type **output) {
454 *output = static_cast<wrapped_type *>(data);
455 delete this;
456 }
457
458 /**
459 * The wrapped data - only public to allow the mild abuse of this facility
460 * done by store_swapout - it gives a wrapped StoreEntry to StoreIO as the
461 * object to be given to the callbacks. That needs to be fully cleaned up!
462 * - RBC 20060820
463 \todo CODE: make this a private field.
464 */
465 void *data; /* the wrapped data */
466
467 private:
468 CBDATA_CLASS2(generic_cbdata);
469 };
470
471 #endif /* SQUID_CBDATA_H */