]> git.ipfire.org Git - thirdparty/squid.git/blob - src/cbdata.h
Fix printf format for size_t and mb_size_t
[thirdparty/squid.git] / src / cbdata.h
1 /*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9 #ifndef SQUID_SRC_CBDATA_H
10 #define SQUID_SRC_CBDATA_H
11
12 #include "typedefs.h"
13
14 /**
15 \page CBDATA Callback Data Allocator API
16
17 \section Introduction
18
19 \par
20 Squid's extensive use of callback functions makes it very
21 susceptible to memory access errors. To address this all callback
22 functions make use of a construct called cbdata. This allows
23 functions doing callbacks to verify that the caller is still
24 valid before making the callback.
25
26 \note cbdata is intended for callback data and is tailored specifically
27 to make callbacks less dangerous leaving as few windows of errors as
28 possible. It is not suitable or intended as a generic RefCount
29 memory allocator.
30
31 \par
32 The AsyncJob/AsyncCall mechanism is preferred over CBDATA.
33 It replaces cbdata with an AsyncCall::Pointer object which
34 performs the same memory protection duties via other means.
35
36 \section Examples Examples
37 \par
38 Here you can find some examples on how to use cbdata, and why.
39
40 \subsection AsyncOpWithoutCBDATA Asynchronous operation without cbdata, showing why cbdata is needed
41 \par
42 For a asyncronous operation with callback functions, the normal
43 sequence of events in programs NOT using cbdata is as follows:
44
45 \code
46 // initialization
47 type_of_data our_data = new ...;
48 ...
49 // Initiate a asyncronous operation, with our_data as callback_data
50 fooOperationStart(bar, callback_func, our_data);
51 ...
52 // The asyncronous operation completes and makes the callback
53 callback_func(callback_data, ....);
54 // Some time later we clean up our data
55 delete our_data;
56 \endcode
57
58 \par
59 However, things become more interesting if we want or need
60 to free the callback_data, or otherwise cancel the callback,
61 before the operation completes. In constructs like this you
62 can quite easily end up with having the memory referenced
63 pointed to by callback_data freed before the callback is invoked
64 causing a program failure or memory corruption:
65
66 \code
67 // initialization
68 type_of_data our_data = new ...;
69 ...
70 // Initiate a asyncronous operation, with our_data as callback_data
71 fooOperationStart(bar, callback_func, our_data);
72 ...
73 // ouch, something bad happened elsewhere.. try to cleanup
74 // but the programmer forgot there is a callback pending from
75 // fooOperationsStart(). An easy thing to forget when writing code
76 // to deal with errors, especially if there may be many different
77 // pending operations.
78 delete our_data;
79 ...
80 // The asyncronous operation completes and makes the callback
81 callback_func(callback_data, ....);
82 // CRASH, the memory pointer to by callback_data is no longer valid
83 // at the time of the callback
84 \endcode
85
86 \subsection AsyncOpWithCBDATA Asyncronous operation with cbdata
87
88 \par
89 The callback data allocator lets us do this in a uniform and
90 safe manner. The callback data allocator is used to allocate,
91 track and free memory pool objects used during callback
92 operations. Allocated memory is locked while the asyncronous
93 operation executes elsewhere, and is freed when the operation
94 completes. The normal sequence of events is:
95
96 \code
97 // initialization
98 type_of_data our_data = new 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 delete our_data;
111 \endcode
112
113 \subsection AsynchronousOpCancelledByCBDATA Asynchronous operation cancelled by cbdata
114
115 \par
116 With this scheme, nothing bad happens if delete gets called
117 before fooOperantionComplete(...).
118
119 \par Initalization
120 \code
121 // initialization
122 type_of_data our_data = new type_of_data;
123 ...
124 // Initiate a asyncronous operation, with our_data as callback_data
125 fooOperationStart(..., callback_func, our_data);
126 ...
127 // do some stuff with it
128 void *local_pointer = cbdataReference(callback_data);
129 ...
130 // something bad happened elsewhere.. cleanup
131 delete our_data;
132 ....
133 // The asyncronous operation completes and makes the callback
134 void *cbdata;
135 if (cbdataReferenceValidDone(local_pointer, &cbdata))
136 // won't be called, as the data is no longer valid
137 callback_func(...., cbdata);
138 delete our_data;
139 \endcode
140
141 \par
142 In this case, when delete is called before cbdataReferenceValidDone(),
143 the callback_data gets marked as invalid.
144 When the callback_data is invalid before executing the callback
145 function, cbdataReferenceValidDone() will return 0 and
146 callback_func is never executed.
147
148 \subsection AddingCBDATAType Adding a new cbdata registered type
149
150 \par
151 To add new module specific data types to the allocator one uses
152 the macro CBDATA_CLASS() in the class private section, and
153 CBDATA_CLASS_INIT() or CBDATA_NAMESPACED_CLASS_INIT() in the
154 class .cc file.
155
156 \code
157 class Foo
158 {
159 CBDATA_CLASS(Foo);
160
161 public:
162 Foo() {}
163 ~Foo() {}
164 };
165 ...
166 CBDATA_CLASS_INIT(Foo);
167 \endcode
168
169 \par
170 These macros create new(), delete() and toCbdata() methods
171 definition in class scope. Any allocate calls must be made with
172 new() and destruction with delete(), they may be called from
173 anywhere.
174
175 \par
176 The class constructor must make sure that all member
177 variables are initialized, and the class destructor that all
178 dynamic memory is released.
179
180 \par
181 The CbcPointer<> template should be used to create a smart-pointer
182 type for simple reference tracking. It provides get() and valid()
183 accessors for use instead of cbdataReferenceValid(), and performs
184 reliable automatic cbdataReference() and cbdataReferenceDone()
185 tracking.
186 Note that it does NOT provide a replacement for cbdataReferenceValidDone().
187
188 */
189
190 /**
191 * cbdata types. Similar to the MEM_* types, but managed in cbdata.cc
192 * A big difference is that cbdata types are dynamically allocated.
193 *
194 * Initially only UNKNOWN type is predefined.
195 * Other types are added at runtime by CBDATA_CLASS().
196 */
197 typedef int cbdata_type;
198 static const cbdata_type CBDATA_UNKNOWN = 0;
199
200 /**
201 * Create a run-time registration of CBDATA component with
202 * the Squid cachemgr
203 */
204 void cbdataRegisterWithCacheManager(void);
205
206 /**
207 * Allocates a new entry of a registered CBDATA type.
208 *
209 * \note For internal CBDATA use only.
210 */
211 void *cbdataInternalAlloc(cbdata_type type, const char *, int);
212
213 /**
214 * Frees a entry allocated by cbdataInternalAlloc().
215 *
216 * Once this has been called cbdataReferenceValid() and
217 * cbdataReferenceValidDone() will return false regardless
218 * of whether there are remaining cbdata references.
219 *
220 * cbdataReferenceDone() must still be called for any active
221 * references to the cbdata entry. The cbdata entry will be freed
222 * only when the last reference is removed.
223 *
224 * \note For internal CBDATA use only.
225 */
226 void *cbdataInternalFree(void *p, const char *, int);
227
228 #if USE_CBDATA_DEBUG
229 void cbdataInternalLockDbg(const void *p, const char *, int);
230 #define cbdataInternalLock(a) cbdataInternalLockDbg(a,__FILE__,__LINE__)
231
232 void cbdataInternalUnlockDbg(const void *p, const char *, int);
233 #define cbdataInternalUnlock(a) cbdataInternalUnlockDbg(a,__FILE__,__LINE__)
234
235 int cbdataInternalReferenceDoneValidDbg(void **p, void **tp, const char *, int);
236 #define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValidDbg((void **)&(var), (ptr), __FILE__,__LINE__)
237
238 #else
239 void cbdataInternalLock(const void *p);
240 void cbdataInternalUnlock(const void *p);
241
242 /**
243 * Removes a reference created by cbdataReference() and checks
244 * it for validity. Meant to be used on the last dereference,
245 * usually to make a callback.
246 *
247 \code
248 void *cbdata;
249 ...
250 if (cbdataReferenceValidDone(reference, &cbdata)) != NULL)
251 callback(..., cbdata);
252 \endcode
253 *
254 * \param var The reference variable. Will be automatically cleared to NULL.
255 * \param ptr A temporary pointer to the referenced data (if valid).
256 */
257 int cbdataInternalReferenceDoneValid(void **p, void **tp);
258 #define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValid((void **)&(var), (ptr))
259
260 #endif /* !CBDATA_DEBUG */
261
262 /**
263 * \param p A cbdata entry reference pointer.
264 *
265 * \retval 0 A reference is stale. The pointer refers to a entry already freed.
266 * \retval true The reference is valid and active.
267 */
268 int cbdataReferenceValid(const void *p);
269
270 /**
271 * Create a run-time registration for the class type with cbdata memory allocator.
272 *
273 * \note For internal CBDATA use only.
274 */
275 cbdata_type cbdataInternalAddType(cbdata_type type, const char *label, int size);
276
277 /**
278 * This needs to be defined FIRST in the class definition.
279 * It plays with private/public states in C++.
280 */
281 #define CBDATA_CLASS(type) \
282 public: \
283 void *operator new(size_t size) { \
284 assert(size == sizeof(type)); \
285 if (!CBDATA_##type) CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type)); \
286 return (type *)cbdataInternalAlloc(CBDATA_##type,__FILE__,__LINE__); \
287 } \
288 void operator delete (void *address) { \
289 if (address) cbdataInternalFree(address,__FILE__,__LINE__); \
290 } \
291 void *toCbdata() { return this; } \
292 private: \
293 static cbdata_type CBDATA_##type;
294
295 /**
296 * Creates a global instance pointer for the CBDATA memory allocator
297 * to allocate and free objects for the matching CBDATA_CLASS().
298 *
299 * Place this in the appropriate .cc file for the class being registered.
300 *
301 * May be placed inside an explicit namespace scope declaration,
302 * or CBDATA_NAMESPACED_CLASS_INIT() used instead.
303 */
304 #define CBDATA_CLASS_INIT(type) cbdata_type type::CBDATA_##type = CBDATA_UNKNOWN
305
306 /**
307 * Creates a global instance pointer for the CBDATA memory allocator
308 * to allocate and free objects for the matching CBDATA_CLASS().
309 *
310 * Place this in the appropriate .cc file for the class being registered.
311 */
312 #define CBDATA_NAMESPACED_CLASS_INIT(namespace, type) cbdata_type namespace::type::CBDATA_##type = CBDATA_UNKNOWN
313
314 /**
315 * Creates a new reference to a cbdata entry. Used when you need to
316 * store a reference in another structure. The reference can later
317 * be verified for validity by cbdataReferenceValid().
318 *
319 * \deprecated Prefer the use of CbcPointer<> smart pointer.
320 *
321 * \param var
322 * The reference variable is a pointer to the entry, in all
323 * aspects identical to the original pointer. But semantically it
324 * is quite different. It is best if the reference is thought of
325 * and handled as a "void *".
326 */
327 #define cbdataReference(var) (cbdataInternalLock(var), var)
328
329 /**
330 * Removes a reference created by cbdataReference().
331 *
332 * \deprecated Prefer the use of CbcPointer<> smart pointer.
333 *
334 * \param var The reference variable. Will be automatically cleared to NULL.
335 */
336 #define cbdataReferenceDone(var) do {if (var) {cbdataInternalUnlock(var); var = NULL;}} while(0)
337
338 /**
339 * A generic wrapper for passing object pointers through cbdata.
340 * Use this when you need to pass callback data to a blocking
341 * operation, but you don't want to/cannot have that pointer be
342 * cbdata itself.
343 */
344 class generic_cbdata
345 {
346 CBDATA_CLASS(generic_cbdata);
347
348 public:
349 generic_cbdata(void *aData) : data(aData) {}
350
351 template<typename wrapped_type>void unwrap(wrapped_type **output) {
352 *output = static_cast<wrapped_type *>(data);
353 delete this;
354 }
355
356 private:
357 void *data;
358 };
359
360 #endif /* SQUID_CBDATA_H */
361