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