Allow Asterisk to compile under GCC 4.10
[asterisk/asterisk.git] / include / asterisk / astobj.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*
20  * Object Model for Asterisk
21  */
22
23 #ifndef _ASTERISK_ASTOBJ_H
24 #define _ASTERISK_ASTOBJ_H
25
26 #include "asterisk/lock.h"
27
28 /*! \file
29  * \brief A set of macros implementing objects and containers.
30  * Macros are used for maximum performance, to support multiple inheritance,
31  * and to be easily integrated into existing structures without additional
32  * malloc calls, etc.
33  *
34  * These macros expect to operate on two different object types, ASTOBJs and
35  * ASTOBJ_CONTAINERs.  These are not actual types, as any struct can be
36  * converted into an ASTOBJ compatible object or container using the supplied
37  * macros.
38  *
39  * <b>Sample Usage:</b>
40  * \code
41  * struct sample_object {
42  *    ASTOBJ_COMPONENTS(struct sample_object);
43  * };
44  *
45  * struct sample_container {
46  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_object);
47  * } super_container;
48  *
49  * void sample_object_destroy(struct sample_object *obj)
50  * {
51  *    free(obj);
52  * }
53  *
54  * int init_stuff()
55  * {
56  *    struct sample_object *obj1;
57  *    struct sample_object *found_obj;
58  *
59  *    obj1 = malloc(sizeof(struct sample_object));
60  *
61  *    ASTOBJ_CONTAINER_INIT(&super_container);
62  *
63  *    ASTOBJ_INIT(obj1);
64  *    ASTOBJ_WRLOCK(obj1);
65  *    ast_copy_string(obj1->name, "obj1", sizeof(obj1->name));
66  *    ASTOBJ_UNLOCK(obj1);
67  *
68  *    ASTOBJ_CONTAINER_LINK(&super_container, obj1);
69  *
70  *    found_obj = ASTOBJ_CONTAINER_FIND(&super_container, "obj1");
71  *
72  *    if(found_obj) {
73  *       printf("Found object: %s", found_obj->name); 
74  *       ASTOBJ_UNREF(found_obj,sample_object_destroy);
75  *    }
76  *
77  *    ASTOBJ_CONTAINER_DESTROYALL(&super_container,sample_object_destroy);
78  *    ASTOBJ_CONTAINER_DESTROY(&super_container);
79  * 
80  *    return 0;
81  * }
82  * \endcode
83  */
84
85 #if defined(__cplusplus) || defined(c_plusplus)
86 extern "C" {
87 #endif
88
89 #define ASTOBJ_DEFAULT_NAMELEN  80
90 #define ASTOBJ_DEFAULT_BUCKETS  256
91 #define ASTOBJ_DEFAULT_HASH             ast_strhash
92
93 #define ASTOBJ_FLAG_MARKED      (1 << 0)                /* Object has been marked for future operation */
94
95 /* C++ is simply a syntactic crutch for those who cannot think for themselves
96    in an object oriented way. */
97
98 /*! \brief Lock an ASTOBJ for reading.
99  */
100 #define ASTOBJ_RDLOCK(object) ast_mutex_lock(&(object)->_lock)
101
102 /*! \brief Lock an ASTOBJ for writing.
103  */
104 #define ASTOBJ_WRLOCK(object) ast_mutex_lock(&(object)->_lock)
105
106 #define ASTOBJ_TRYWRLOCK(object) ast_mutex_trylock(&(object)->_lock)
107
108 /*! \brief Unlock a locked object. */
109 #define ASTOBJ_UNLOCK(object) ast_mutex_unlock(&(object)->_lock)
110
111 #ifdef ASTOBJ_CONTAINER_HASHMODEL 
112 #define __ASTOBJ_HASH(type,hashes) \
113         type *next[hashes] 
114 #else 
115 #define __ASTOBJ_HASH(type,hashes) \
116         type *next[1] 
117 #endif  
118
119 /*! \brief Add ASTOBJ components to a struct (without locking support).
120  *
121  * \param type The datatype of the object.
122  * \param namelen The length to make the name char array.
123  * \param hashes The number of containers the object can be present in.
124  *
125  * This macro adds components to a struct to make it an ASTOBJ.  This macro
126  * differs from ASTOBJ_COMPONENTS_FULL in that it does not create a mutex for
127  * locking.
128  *
129  * <b>Sample Usage:</b>
130  * \code
131  * struct sample_struct {
132  *    ASTOBJ_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
133  * };
134  * \endcode
135  */
136 #define ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes) \
137         char name[namelen]; \
138         unsigned int refcount; \
139         unsigned int objflags; \
140         __ASTOBJ_HASH(type,hashes)
141         
142 /*! \brief Add ASTOBJ components to a struct (without locking support).
143  *
144  * \param type The datatype of the object.
145  *
146  * This macro works like #ASTOBJ_COMPONENTS_NOLOCK_FULL() except it only accepts a
147  * type and uses default values for namelen and hashes.
148  * 
149  * <b>Sample Usage:</b>
150  * \code
151  * struct sample_struct_componets {
152  *    ASTOBJ_COMPONENTS_NOLOCK(struct sample_struct);
153  * };
154  * \endcode
155  */
156 #define ASTOBJ_COMPONENTS_NOLOCK(type) \
157         ASTOBJ_COMPONENTS_NOLOCK_FULL(type,ASTOBJ_DEFAULT_NAMELEN,1)
158
159 /*! \brief Add ASTOBJ components to a struct (with locking support).
160  *
161  * \param type The datatype of the object.
162  *
163  * This macro works like #ASTOBJ_COMPONENTS_NOLOCK() except it includes locking
164  * support.
165  *
166  * <b>Sample Usage:</b>
167  * \code
168  * struct sample_struct {
169  *    ASTOBJ_COMPONENTS(struct sample_struct);
170  * };
171  * \endcode
172  */
173 #define ASTOBJ_COMPONENTS(type) \
174         ASTOBJ_COMPONENTS_NOLOCK(type); \
175         ast_mutex_t _lock; 
176         
177 /*! \brief Add ASTOBJ components to a struct (with locking support).
178  *
179  * \param type The datatype of the object.
180  * \param namelen The length to make the name char array.
181  * \param hashes The number of containers the object can be present in.
182  *
183  * This macro adds components to a struct to make it an ASTOBJ and includes
184  * support for locking.
185  *
186  * <b>Sample Usage:</b>
187  * \code
188  * struct sample_struct {
189  *    ASTOBJ_COMPONENTS_FULL(struct sample_struct,1,1);
190  * };
191  * \endcode
192  */
193 #define ASTOBJ_COMPONENTS_FULL(type,namelen,hashes) \
194         ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes); \
195         ast_mutex_t _lock; 
196
197 /*! \brief Increment an object reference count.
198  * \param object A pointer to the object to operate on.
199  * \return The object.
200  */
201 #define ASTOBJ_REF(object) \
202         ({ \
203                 ASTOBJ_WRLOCK(object); \
204                 (object)->refcount++; \
205                 ASTOBJ_UNLOCK(object); \
206                 (object); \
207         })
208         
209 /*! \brief Decrement the reference count on an object.
210  *
211  * \param object A pointer the object to operate on.
212  * \param destructor The destructor to call if the object is no longer referenced.  It will be passed the pointer as an argument.
213  *
214  * This macro unreferences an object and calls the specfied destructor if the
215  * object is no longer referenced.  The destructor should free the object if it
216  * was dynamically allocated.
217  */
218 #define ASTOBJ_UNREF(object,destructor) \
219         do { \
220                 int newcount = 0; \
221                 ASTOBJ_WRLOCK(object); \
222                 if (__builtin_expect((object)->refcount > 0, 1)) \
223                         newcount = --((object)->refcount); \
224                 else \
225                         ast_log(AST_LOG_WARNING, "Unreferencing unreferenced (object)!\n"); \
226                 ASTOBJ_UNLOCK(object); \
227                 if (newcount == 0) { \
228                         ast_mutex_destroy(&(object)->_lock); \
229                         destructor((object)); \
230                 } \
231                 (object) = NULL; \
232         } while(0)
233
234 /*! \brief Mark an ASTOBJ by adding the #ASTOBJ_FLAG_MARKED flag to its objflags mask. 
235  * \param object A pointer to the object to operate on.
236  *
237  * This macro "marks" an object.  Marked objects can later be unlinked from a container using
238  * #ASTOBJ_CONTAINER_PRUNE_MARKED().
239  * 
240  */
241 #define ASTOBJ_MARK(object) \
242         do { \
243                 ASTOBJ_WRLOCK(object); \
244                 (object)->objflags |= ASTOBJ_FLAG_MARKED; \
245                 ASTOBJ_UNLOCK(object); \
246         } while(0)
247         
248 /*! \brief Unmark an ASTOBJ by subtracting the #ASTOBJ_FLAG_MARKED flag from its objflags mask.
249  * \param object A pointer to the object to operate on.
250  */
251 #define ASTOBJ_UNMARK(object) \
252         do { \
253                 ASTOBJ_WRLOCK(object); \
254                 (object)->objflags &= ~ASTOBJ_FLAG_MARKED; \
255                 ASTOBJ_UNLOCK(object); \
256         } while(0)
257
258 /*! \brief Initialize an object.
259  * \param object A pointer to the object to operate on.
260  *
261  * \note This should only be used on objects that support locking (objects
262  * created with #ASTOBJ_COMPONENTS() or #ASTOBJ_COMPONENTS_FULL())
263  */
264 #define ASTOBJ_INIT(object) \
265         do { \
266                 ast_mutex_init(&(object)->_lock); \
267                 object->name[0] = '\0'; \
268                 object->refcount = 1; \
269         } while(0)
270
271 /* Containers for objects -- current implementation is linked lists, but
272    should be able to be converted to hashes relatively easily */
273
274 /*! \brief Lock an ASTOBJ_CONTAINER for reading.
275  */
276 #define ASTOBJ_CONTAINER_RDLOCK(container) ast_mutex_lock(&(container)->_lock)
277
278 /*! \brief Lock an ASTOBJ_CONTAINER for writing. 
279  */
280 #define ASTOBJ_CONTAINER_WRLOCK(container) ast_mutex_lock(&(container)->_lock)
281
282 /*! \brief Unlock an ASTOBJ_CONTAINER. */
283 #define ASTOBJ_CONTAINER_UNLOCK(container) ast_mutex_unlock(&(container)->_lock)
284
285 #ifdef ASTOBJ_CONTAINER_HASHMODEL
286 #error "Hash model for object containers not yet implemented!"
287 #else
288 /* Linked lists */
289
290 /*! \brief Create a container for ASTOBJs (without locking support).
291  *
292  * \param type The type of objects the container will hold.
293  * \param hashes Currently unused.
294  * \param buckets Currently unused.
295  *
296  * This macro is used to create a container for ASTOBJs without locking
297  * support.
298  *
299  * <b>Sample Usage:</b>
300  * \code
301  * struct sample_struct_nolock_container {
302  *    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
303  * };
304  * \endcode
305  */
306 #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,hashes,buckets) \
307         type *head
308
309 /*! \brief Initialize a container.
310  *
311  * \param container A pointer to the container to initialize.
312  * \param hashes Currently unused.
313  * \param buckets Currently unused.
314  *
315  * This macro initializes a container.  It should only be used on containers
316  * that support locking.
317  * 
318  * <b>Sample Usage:</b>
319  * \code
320  * struct sample_struct_container {
321  *    ASTOBJ_CONTAINER_COMPONENTS_FULL(struct sample_struct,1,1);
322  * } container;
323  *
324  * int func()
325  * {
326  *    ASTOBJ_CONTAINER_INIT_FULL(&container,1,1);
327  * }
328  * \endcode
329  */
330 #define ASTOBJ_CONTAINER_INIT_FULL(container,hashes,buckets) \
331         do { \
332                 ast_mutex_init(&(container)->_lock); \
333         } while(0)
334         
335 /*! \brief Destroy a container.
336  *
337  * \param container A pointer to the container to destroy.
338  * \param hashes Currently unused.
339  * \param buckets Currently unused.
340  *
341  * This macro frees up resources used by a container.  It does not operate on
342  * the objects in the container.  To unlink the objects from the container use
343  * #ASTOBJ_CONTAINER_DESTROYALL().
344  *
345  * \note This macro should only be used on containers with locking support.
346  */
347 #define ASTOBJ_CONTAINER_DESTROY_FULL(container,hashes,buckets) \
348         do { \
349                 ast_mutex_destroy(&(container)->_lock); \
350         } while(0)
351
352 /*! \brief Iterate through the objects in a container.
353  *
354  * \param container A pointer to the container to traverse.
355  * \param continue A condition to allow the traversal to continue.
356  * \param eval A statement to evaluate in the iteration loop.
357  *
358  * This is macro is a little complicated, but it may help to think of it as a
359  * loop.  Basically it iterates through the specfied containter as long as the
360  * condition is met.  Two variables, iterator and next, are provided for use in
361  * your \p eval statement.  See the sample code for an example.
362  *
363  * <b>Sample Usage:</b>
364  * \code
365  * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, {
366  *    ASTOBJ_RDLOCK(iterator);
367  *    printf("Currently iterating over '%s'\n", iterator->name);
368  *    ASTOBJ_UNLOCK(iterator);
369  * } );
370  * \endcode
371  *
372  * \code
373  * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, sample_func(iterator));
374  * \endcode
375  */
376 #define ASTOBJ_CONTAINER_TRAVERSE(container,continue,eval) \
377         do { \
378                 typeof((container)->head) iterator; \
379                 typeof((container)->head) next; \
380                 ASTOBJ_CONTAINER_RDLOCK(container); \
381                 next = (container)->head; \
382                 while((continue) && (iterator = next)) { \
383                         next = iterator->next[0]; \
384                         eval; \
385                 } \
386                 ASTOBJ_CONTAINER_UNLOCK(container); \
387         } while(0)
388
389 /*! \brief Find an object in a container.
390  *
391  * \param container A pointer to the container to search.
392  * \param namestr The name to search for.
393  *
394  * Use this function to find an object with the specfied name in a container.
395  *
396  * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
397  * be used to free the additional reference created by this macro.
398  *
399  * \return A new reference to the object located or NULL if nothing is found.
400  */
401 #define ASTOBJ_CONTAINER_FIND(container,namestr) \
402         ({ \
403                 typeof((container)->head) found = NULL; \
404                 ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
405                         if (!(strcasecmp(iterator->name, (namestr)))) \
406                                 found = ASTOBJ_REF(iterator); \
407                 } while (0)); \
408                 found; \
409         })
410
411 /*! \brief Find an object in a container.
412  * 
413  * \param container A pointer to the container to search.
414  * \param data The data to search for.
415  * \param field The field/member of the container's objects to search.
416  * \param hashfunc The hash function to use, currently not implemented.
417  * \param hashoffset The hash offset to use, currently not implemented.
418  * \param comparefunc The function used to compare the field and data values.
419  *
420  * This macro iterates through a container passing the specified field and data
421  * elements to the specified comparefunc.  The function should return 0 when a match is found.
422  * 
423  * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
424  * be used to free the additional reference created by this macro.
425  *
426  * \return A pointer to the object located or NULL if nothing is found.
427  */
428 #define ASTOBJ_CONTAINER_FIND_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
429         ({ \
430                 typeof((container)->head) found = NULL; \
431                 ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
432                         ASTOBJ_RDLOCK(iterator); \
433                         if (!(comparefunc(iterator->field, (data)))) { \
434                                 found = ASTOBJ_REF(iterator); \
435                         } \
436                         ASTOBJ_UNLOCK(iterator); \
437                 } while (0)); \
438                 found; \
439         })
440
441 /*! \brief Empty a container.
442  *
443  * \param container A pointer to the container to operate on.
444  * \param destructor A destructor function to call on each object.
445  *
446  * This macro loops through a container removing all the items from it using
447  * #ASTOBJ_UNREF().  This does not destroy the container itself, use
448  * #ASTOBJ_CONTAINER_DESTROY() for that.
449  *
450  * \note If any object in the container is only referenced by the container,
451  * the destructor will be called for that object once it has been removed.
452  */
453 #define ASTOBJ_CONTAINER_DESTROYALL(container,destructor) \
454         do { \
455                 typeof((container)->head) iterator; \
456                 ASTOBJ_CONTAINER_WRLOCK(container); \
457                 while((iterator = (container)->head)) { \
458                         (container)->head = (iterator)->next[0]; \
459                         ASTOBJ_UNREF(iterator,destructor); \
460                 } \
461                 ASTOBJ_CONTAINER_UNLOCK(container); \
462         } while(0)
463
464 /*! \brief Remove an object from a container.
465  *
466  * \param container A pointer to the container to operate on.
467  * \param obj A pointer to the object to remove.
468  *
469  * This macro iterates through a container and removes the specfied object if
470  * it exists in the container.
471  *
472  * \note This macro does not destroy any objects, it simply unlinks
473  * them from the list.  No destructors are called.
474  *
475  * \return The container's reference to the removed object or NULL if no
476  * matching object was found.
477  */
478 #define ASTOBJ_CONTAINER_UNLINK(container,obj) \
479         ({ \
480                 typeof((container)->head) found = NULL; \
481                 typeof((container)->head) prev = NULL; \
482                 ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
483                         if (iterator == obj) { \
484                                 found = iterator; \
485                                 found->next[0] = NULL; \
486                                 ASTOBJ_CONTAINER_WRLOCK(container); \
487                                 if (prev) \
488                                         prev->next[0] = next; \
489                                 else \
490                                         (container)->head = next; \
491                                 ASTOBJ_CONTAINER_UNLOCK(container); \
492                         } \
493                         prev = iterator; \
494                 } while (0)); \
495                 found; \
496         })
497
498 /*! \brief Find and remove an object from a container.
499  * 
500  * \param container A pointer to the container to operate on.
501  * \param namestr The name of the object to remove.
502  *
503  * This macro iterates through a container and removes the first object with
504  * the specfied name from the container.
505  *
506  * \note This macro does not destroy any objects, it simply unlinks
507  * them.  No destructors are called.
508  *
509  * \return The container's reference to the removed object or NULL if no
510  * matching object was found.
511  */
512 #define ASTOBJ_CONTAINER_FIND_UNLINK(container,namestr) \
513         ({ \
514                 typeof((container)->head) found = NULL; \
515                 typeof((container)->head) prev = NULL; \
516                 ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
517                         if (!(strcasecmp(iterator->name, (namestr)))) { \
518                                 found = iterator; \
519                                 found->next[0] = NULL; \
520                                 ASTOBJ_CONTAINER_WRLOCK(container); \
521                                 if (prev) \
522                                         prev->next[0] = next; \
523                                 else \
524                                         (container)->head = next; \
525                                 ASTOBJ_CONTAINER_UNLOCK(container); \
526                         } \
527                         prev = iterator; \
528                 } while (0)); \
529                 found; \
530         })
531
532 /*! \brief Find and remove an object in a container.
533  * 
534  * \param container A pointer to the container to search.
535  * \param data The data to search for.
536  * \param field The field/member of the container's objects to search.
537  * \param hashfunc The hash function to use, currently not implemented.
538  * \param hashoffset The hash offset to use, currently not implemented.
539  * \param comparefunc The function used to compare the field and data values.
540  *
541  * This macro iterates through a container passing the specified field and data
542  * elements to the specified comparefunc.  The function should return 0 when a match is found.
543  * If a match is found it is removed from the list. 
544  *
545  * \note This macro does not destroy any objects, it simply unlinks
546  * them.  No destructors are called.
547  *
548  * \return The container's reference to the removed object or NULL if no match
549  * was found.
550  */
551 #define ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
552         ({ \
553                 typeof((container)->head) found = NULL; \
554                 typeof((container)->head) prev = NULL; \
555                 ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
556                         ASTOBJ_RDLOCK(iterator); \
557                         if (!(comparefunc(iterator->field, (data)))) { \
558                                 found = iterator; \
559                                 found->next[0] = NULL; \
560                                 ASTOBJ_CONTAINER_WRLOCK(container); \
561                                 if (prev) \
562                                         prev->next[0] = next; \
563                                 else \
564                                         (container)->head = next; \
565                                 ASTOBJ_CONTAINER_UNLOCK(container); \
566                         } \
567                         ASTOBJ_UNLOCK(iterator); \
568                         prev = iterator; \
569                 } while (0)); \
570                 found; \
571         })
572
573 /*! \brief Add an object to the end of a container.
574  *
575  * \param container A pointer to the container to operate on.
576  * \param newobj A pointer to the object to be added.
577  *
578  * This macro adds an object to the end of a container.
579  */
580 #define ASTOBJ_CONTAINER_LINK_END(container,newobj) \
581         do { \
582                 typeof((container)->head) iterator; \
583                 typeof((container)->head) next; \
584                 typeof((container)->head) prev; \
585                 ASTOBJ_CONTAINER_RDLOCK(container); \
586                 prev = NULL; \
587                 next = (container)->head; \
588                 while((iterator = next)) { \
589                         next = iterator->next[0]; \
590                         prev = iterator; \
591                 } \
592                 if(prev) { \
593                         ASTOBJ_CONTAINER_WRLOCK((container)); \
594                         prev->next[0] = ASTOBJ_REF(newobj); \
595                         (newobj)->next[0] = NULL; \
596                         ASTOBJ_CONTAINER_UNLOCK((container)); \
597                 } else { \
598                         ASTOBJ_CONTAINER_LINK_START((container),(newobj)); \
599                 } \
600                 ASTOBJ_CONTAINER_UNLOCK((container)); \
601         } while(0)
602
603 /*! \brief Add an object to the front of a container.
604  *
605  * \param container A pointer to the container to operate on.
606  * \param newobj A pointer to the object to be added.
607  *
608  * This macro adds an object to the start of a container.
609  */
610 #define ASTOBJ_CONTAINER_LINK_START(container,newobj) \
611         do { \
612                 ASTOBJ_CONTAINER_WRLOCK(container); \
613                 (newobj)->next[0] = (container)->head; \
614                 (container)->head = ASTOBJ_REF(newobj); \
615                 ASTOBJ_CONTAINER_UNLOCK(container); \
616         } while(0)
617
618 /*! \brief Remove an object from the front of a container.
619  *
620  * \param container A pointer to the container to operate on.
621  *
622  * This macro removes the first object in a container.
623  *
624  * \note This macro does not destroy any objects, it simply unlinks
625  * them from the list.  No destructors are called.
626  *
627  * \return The container's reference to the removed object or NULL if no
628  * matching object was found.
629  */
630 #define ASTOBJ_CONTAINER_UNLINK_START(container) \
631         ({ \
632                 typeof((container)->head) found = NULL; \
633                 ASTOBJ_CONTAINER_WRLOCK(container); \
634                 if((container)->head) { \
635                         found = (container)->head; \
636                         (container)->head = (container)->head->next[0]; \
637                         found->next[0] = NULL; \
638                 } \
639                 ASTOBJ_CONTAINER_UNLOCK(container); \
640                 found; \
641         })
642
643 /*! \brief Prune marked objects from a container.
644  *
645  * \param container A pointer to the container to prune.
646  * \param destructor A destructor function to call on each marked object.
647  * 
648  * This macro iterates through the specfied container and prunes any marked
649  * objects executing the specfied destructor if necessary.
650  */
651 #define ASTOBJ_CONTAINER_PRUNE_MARKED(container,destructor) \
652         do { \
653                 typeof((container)->head) prev = NULL; \
654                 ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { \
655                         ASTOBJ_RDLOCK(iterator); \
656                         if (iterator->objflags & ASTOBJ_FLAG_MARKED) { \
657                                 ASTOBJ_CONTAINER_WRLOCK(container); \
658                                 if (prev) \
659                                         prev->next[0] = next; \
660                                 else \
661                                         (container)->head = next; \
662                                 ASTOBJ_CONTAINER_UNLOCK(container); \
663                                 ASTOBJ_UNLOCK(iterator); \
664                                 ASTOBJ_UNREF(iterator,destructor); \
665                                 continue; \
666                         } \
667                         ASTOBJ_UNLOCK(iterator); \
668                         prev = iterator; \
669                 } while (0)); \
670         } while(0)
671
672 /*! \brief Add an object to a container.
673  *
674  * \param container A pointer to the container to operate on.
675  * \param newobj A pointer to the object to be added.
676  * \param data Currently unused.
677  * \param field Currently unused.
678  * \param hashfunc Currently unused.
679  * \param hashoffset Currently unused.
680  * \param comparefunc Currently unused.
681  *
682  * Currently this function adds an object to the head of the list.  One day it
683  * will support adding objects atthe position specified using the various
684  * options this macro offers.
685  */
686 #define ASTOBJ_CONTAINER_LINK_FULL(container,newobj,data,field,hashfunc,hashoffset,comparefunc) \
687         do { \
688                 ASTOBJ_CONTAINER_WRLOCK(container); \
689                 (newobj)->next[0] = (container)->head; \
690                 (container)->head = ASTOBJ_REF(newobj); \
691                 ASTOBJ_CONTAINER_UNLOCK(container); \
692         } while(0)
693
694 #endif /* List model */
695
696 /* Common to hash and linked list models */
697
698 /*! \brief Create a container for ASTOBJs (without locking support).
699  *
700  * \param type The type of objects the container will hold.
701  *
702  * This macro is used to create a container for ASTOBJs without locking
703  * support.
704  *
705  * <b>Sample Usage:</b>
706  * \code
707  * struct sample_struct_nolock_container {
708  *    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(struct sample_struct);
709  * };
710  * \endcode
711  */
712 #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) \
713         ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,1,ASTOBJ_DEFAULT_BUCKETS)
714
715
716 /*! \brief Create a container for ASTOBJs (with locking support).
717  *
718  * \param type The type of objects the container will hold.
719  *
720  * This macro is used to create a container for ASTOBJs with locking support.
721  *
722  * <b>Sample Usage:</b>
723  * \code
724  * struct sample_struct_container {
725  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
726  * };
727  * \endcode
728  */
729 #define ASTOBJ_CONTAINER_COMPONENTS(type) \
730         ast_mutex_t _lock; \
731         ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type)
732
733 /*! \brief Initialize a container.
734  *
735  * \param container A pointer to the container to initialize.
736  *
737  * This macro initializes a container.  It should only be used on containers
738  * that support locking.
739  * 
740  * <b>Sample Usage:</b>
741  * \code
742  * struct sample_struct_container {
743  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
744  * } container;
745  *
746  * int func()
747  * {
748  *    ASTOBJ_CONTAINER_INIT(&container);
749  * }
750  * \endcode
751  */
752 #define ASTOBJ_CONTAINER_INIT(container) \
753         ASTOBJ_CONTAINER_INIT_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
754
755 /*! \brief Destroy a container.
756  *
757  * \param container A pointer to the container to destory.
758  *
759  * This macro frees up resources used by a container.  It does not operate on
760  * the objects in the container.  To unlink the objects from the container use
761  * #ASTOBJ_CONTAINER_DESTROYALL().
762  *
763  * \note This macro should only be used on containers with locking support.
764  */
765 #define ASTOBJ_CONTAINER_DESTROY(container) \
766         ASTOBJ_CONTAINER_DESTROY_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
767
768 /*! \brief Add an object to a container.
769  *
770  * \param container A pointer to the container to operate on.
771  * \param newobj A pointer to the object to be added.
772  *
773  * Currently this macro adds an object to the head of a container.  One day it
774  * should add an object in alphabetical order.
775  */
776 #define ASTOBJ_CONTAINER_LINK(container,newobj) \
777         ASTOBJ_CONTAINER_LINK_FULL(container,newobj,(newobj)->name,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
778
779 /*! \brief Mark all the objects in a container.
780  * \param container A pointer to the container to operate on.
781  */
782 #define ASTOBJ_CONTAINER_MARKALL(container) \
783         ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_MARK(iterator))
784
785 /*! \brief Unmark all the objects in a container.
786  * \param container A pointer to the container to operate on.
787  */
788 #define ASTOBJ_CONTAINER_UNMARKALL(container) \
789         ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_UNMARK(iterator))
790
791 /*! \brief Dump information about an object into a string.
792  *
793  * \param s A pointer to the string buffer to use.
794  * \param slen The length of s.
795  * \param obj A pointer to the object to dump.
796  *
797  * This macro dumps a text representation of the name, objectflags, and
798  * refcount fields of an object to the specfied string buffer.
799  */
800 #define ASTOBJ_DUMP(s,slen,obj) \
801         snprintf((s),(slen),"name: %s\nobjflags: %u\nrefcount: %u\n\n", (obj)->name, (obj)->objflags, (obj)->refcount);
802
803 /*! \brief Dump information about all the objects in a container to a file descriptor.
804  *
805  * \param fd The file descriptor to write to.
806  * \param s A string buffer, same as #ASTOBJ_DUMP().
807  * \param slen The length of s, same as #ASTOBJ_DUMP().
808  * \param container A pointer to the container to dump.
809  *
810  * This macro dumps a text representation of the name, objectflags, and
811  * refcount fields of all the objects in a container to the specified file
812  * descriptor.
813  */
814 #define ASTOBJ_CONTAINER_DUMP(fd,s,slen,container) \
815         ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { ASTOBJ_DUMP(s,slen,iterator); ast_cli(fd, "%s", s); } while(0))
816
817 #if defined(__cplusplus) || defined(c_plusplus)
818 }
819 #endif
820
821 #endif /* _ASTERISK_ASTOBJ_H */