astobj.h 25 KB

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