Wed Jan 8 2020 09:49:42
Asterisk developer's documentation
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
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
/*
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 */
lock.h
Asterisk locking-related definitions:
include
asterisk
astobj.h
Generated by
1.8.5