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