Asterisk - The Open Source Telephony Project GIT-master-f36a736
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 <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/*! \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)
88extern "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_components {
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: