apr_ring.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * This code draws heavily from the 4.4BSD <sys/queue.h> macros
  18. * and Dean Gaudet's "splim/ring.h".
  19. * <http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h>
  20. * <http://www.arctic.org/~dean/splim/>
  21. *
  22. * We'd use Dean's code directly if we could guarantee the
  23. * availability of inline functions.
  24. */
  25. #ifndef APR_RING_H
  26. #define APR_RING_H
  27. /**
  28. * @file apr_ring.h
  29. * @brief APR Rings
  30. */
  31. /*
  32. * for offsetof()
  33. */
  34. #include "apr_general.h"
  35. /**
  36. * @defgroup apr_ring Ring Macro Implementations
  37. * @ingroup APR
  38. * A ring is a kind of doubly-linked list that can be manipulated
  39. * without knowing where its head is.
  40. * @{
  41. */
  42. /**
  43. * The Ring Element
  44. *
  45. * A ring element struct is linked to the other elements in the ring
  46. * through its ring entry field, e.g.
  47. * <pre>
  48. * struct my_element_t {
  49. * APR_RING_ENTRY(my_element_t) link;
  50. * int foo;
  51. * char *bar;
  52. * };
  53. * </pre>
  54. *
  55. * An element struct may be put on more than one ring if it has more
  56. * than one APR_RING_ENTRY field. Each APR_RING_ENTRY has a corresponding
  57. * APR_RING_HEAD declaration.
  58. *
  59. * @warning For strict C standards compliance you should put the APR_RING_ENTRY
  60. * first in the element struct unless the head is always part of a larger
  61. * object with enough earlier fields to accommodate the offsetof() used
  62. * to compute the ring sentinel below. You can usually ignore this caveat.
  63. */
  64. #define APR_RING_ENTRY(elem) \
  65. struct { \
  66. struct elem * volatile next; \
  67. struct elem * volatile prev; \
  68. }
  69. /**
  70. * The Ring Head
  71. *
  72. * Each ring is managed via its head, which is a struct declared like this:
  73. * <pre>
  74. * APR_RING_HEAD(my_ring_t, my_element_t);
  75. * struct my_ring_t ring, *ringp;
  76. * </pre>
  77. *
  78. * This struct looks just like the element link struct so that we can
  79. * be sure that the typecasting games will work as expected.
  80. *
  81. * The first element in the ring is next after the head, and the last
  82. * element is just before the head.
  83. */
  84. #define APR_RING_HEAD(head, elem) \
  85. struct head { \
  86. struct elem * volatile next; \
  87. struct elem * volatile prev; \
  88. }
  89. /**
  90. * The Ring Sentinel
  91. *
  92. * This is the magic pointer value that occurs before the first and
  93. * after the last elements in the ring, computed from the address of
  94. * the ring's head. The head itself isn't an element, but in order to
  95. * get rid of all the special cases when dealing with the ends of the
  96. * ring, we play typecasting games to make it look like one.
  97. *
  98. * Here is a diagram to illustrate the arrangements of the next and
  99. * prev pointers of each element in a single ring. Note that they point
  100. * to the start of each element, not to the APR_RING_ENTRY structure.
  101. *
  102. * <pre>
  103. * +->+------+<-+ +->+------+<-+ +->+------+<-+
  104. * | |struct| | | |struct| | | |struct| |
  105. * / | elem | \/ | elem | \/ | elem | \
  106. * ... | | /\ | | /\ | | ...
  107. * +------+ | | +------+ | | +------+
  108. * ...--|prev | | +--|ring | | +--|prev |
  109. * | next|--+ | entry|--+ | next|--...
  110. * +------+ +------+ +------+
  111. * | etc. | | etc. | | etc. |
  112. * : : : : : :
  113. * </pre>
  114. *
  115. * The APR_RING_HEAD is nothing but a bare APR_RING_ENTRY. The prev
  116. * and next pointers in the first and last elements don't actually
  117. * point to the head, they point to a phantom place called the
  118. * sentinel. Its value is such that last->next->next == first because
  119. * the offset from the sentinel to the head's next pointer is the same
  120. * as the offset from the start of an element to its next pointer.
  121. * This also works in the opposite direction.
  122. *
  123. * <pre>
  124. * last first
  125. * +->+------+<-+ +->sentinel<-+ +->+------+<-+
  126. * | |struct| | | | | |struct| |
  127. * / | elem | \/ \/ | elem | \
  128. * ... | | /\ /\ | | ...
  129. * +------+ | | +------+ | | +------+
  130. * ...--|prev | | +--|ring | | +--|prev |
  131. * | next|--+ | head|--+ | next|--...
  132. * +------+ +------+ +------+
  133. * | etc. | | etc. |
  134. * : : : :
  135. * </pre>
  136. *
  137. * Note that the offset mentioned above is different for each kind of
  138. * ring that the element may be on, and each kind of ring has a unique
  139. * name for its APR_RING_ENTRY in each element, and has its own type
  140. * for its APR_RING_HEAD.
  141. *
  142. * Note also that if the offset is non-zero (which is required if an
  143. * element has more than one APR_RING_ENTRY), the unreality of the
  144. * sentinel may have bad implications on very perverse implementations
  145. * of C -- see the warning in APR_RING_ENTRY.
  146. *
  147. * @param hp The head of the ring
  148. * @param elem The name of the element struct
  149. * @param link The name of the APR_RING_ENTRY in the element struct
  150. */
  151. #define APR_RING_SENTINEL(hp, elem, link) \
  152. (struct elem *)((char *)(&(hp)->next) - APR_OFFSETOF(struct elem, link))
  153. /**
  154. * The first element of the ring
  155. * @param hp The head of the ring
  156. */
  157. #define APR_RING_FIRST(hp) (hp)->next
  158. /**
  159. * The last element of the ring
  160. * @param hp The head of the ring
  161. */
  162. #define APR_RING_LAST(hp) (hp)->prev
  163. /**
  164. * The next element in the ring
  165. * @param ep The current element
  166. * @param link The name of the APR_RING_ENTRY in the element struct
  167. */
  168. #define APR_RING_NEXT(ep, link) (ep)->link.next
  169. /**
  170. * The previous element in the ring
  171. * @param ep The current element
  172. * @param link The name of the APR_RING_ENTRY in the element struct
  173. */
  174. #define APR_RING_PREV(ep, link) (ep)->link.prev
  175. /**
  176. * Initialize a ring
  177. * @param hp The head of the ring
  178. * @param elem The name of the element struct
  179. * @param link The name of the APR_RING_ENTRY in the element struct
  180. */
  181. #define APR_RING_INIT(hp, elem, link) do { \
  182. APR_RING_FIRST((hp)) = APR_RING_SENTINEL((hp), elem, link); \
  183. APR_RING_LAST((hp)) = APR_RING_SENTINEL((hp), elem, link); \
  184. } while (0)
  185. /**
  186. * Determine if a ring is empty
  187. * @param hp The head of the ring
  188. * @param elem The name of the element struct
  189. * @param link The name of the APR_RING_ENTRY in the element struct
  190. * @return true or false
  191. */
  192. #define APR_RING_EMPTY(hp, elem, link) \
  193. (APR_RING_FIRST((hp)) == APR_RING_SENTINEL((hp), elem, link))
  194. /**
  195. * Initialize a singleton element
  196. * @param ep The element
  197. * @param link The name of the APR_RING_ENTRY in the element struct
  198. */
  199. #define APR_RING_ELEM_INIT(ep, link) do { \
  200. APR_RING_NEXT((ep), link) = (ep); \
  201. APR_RING_PREV((ep), link) = (ep); \
  202. } while (0)
  203. /**
  204. * Splice the sequence ep1..epN into the ring before element lep
  205. * (..lep.. becomes ..ep1..epN..lep..)
  206. * @warning This doesn't work for splicing before the first element or on
  207. * empty rings... see APR_RING_SPLICE_HEAD for one that does
  208. * @param lep Element in the ring to splice before
  209. * @param ep1 First element in the sequence to splice in
  210. * @param epN Last element in the sequence to splice in
  211. * @param link The name of the APR_RING_ENTRY in the element struct
  212. */
  213. #define APR_RING_SPLICE_BEFORE(lep, ep1, epN, link) do { \
  214. APR_RING_NEXT((epN), link) = (lep); \
  215. APR_RING_PREV((ep1), link) = APR_RING_PREV((lep), link); \
  216. APR_RING_NEXT(APR_RING_PREV((lep), link), link) = (ep1); \
  217. APR_RING_PREV((lep), link) = (epN); \
  218. } while (0)
  219. /**
  220. * Splice the sequence ep1..epN into the ring after element lep
  221. * (..lep.. becomes ..lep..ep1..epN..)
  222. * @warning This doesn't work for splicing after the last element or on
  223. * empty rings... see APR_RING_SPLICE_TAIL for one that does
  224. * @param lep Element in the ring to splice after
  225. * @param ep1 First element in the sequence to splice in
  226. * @param epN Last element in the sequence to splice in
  227. * @param link The name of the APR_RING_ENTRY in the element struct
  228. */
  229. #define APR_RING_SPLICE_AFTER(lep, ep1, epN, link) do { \
  230. APR_RING_PREV((ep1), link) = (lep); \
  231. APR_RING_NEXT((epN), link) = APR_RING_NEXT((lep), link); \
  232. APR_RING_PREV(APR_RING_NEXT((lep), link), link) = (epN); \
  233. APR_RING_NEXT((lep), link) = (ep1); \
  234. } while (0)
  235. /**
  236. * Insert the element nep into the ring before element lep
  237. * (..lep.. becomes ..nep..lep..)
  238. * @warning This doesn't work for inserting before the first element or on
  239. * empty rings... see APR_RING_INSERT_HEAD for one that does
  240. * @param lep Element in the ring to insert before
  241. * @param nep Element to insert
  242. * @param link The name of the APR_RING_ENTRY in the element struct
  243. */
  244. #define APR_RING_INSERT_BEFORE(lep, nep, link) \
  245. APR_RING_SPLICE_BEFORE((lep), (nep), (nep), link)
  246. /**
  247. * Insert the element nep into the ring after element lep
  248. * (..lep.. becomes ..lep..nep..)
  249. * @warning This doesn't work for inserting after the last element or on
  250. * empty rings... see APR_RING_INSERT_TAIL for one that does
  251. * @param lep Element in the ring to insert after
  252. * @param nep Element to insert
  253. * @param link The name of the APR_RING_ENTRY in the element struct
  254. */
  255. #define APR_RING_INSERT_AFTER(lep, nep, link) \
  256. APR_RING_SPLICE_AFTER((lep), (nep), (nep), link)
  257. /**
  258. * Splice the sequence ep1..epN into the ring before the first element
  259. * (..hp.. becomes ..hp..ep1..epN..)
  260. * @param hp Head of the ring
  261. * @param ep1 First element in the sequence to splice in
  262. * @param epN Last element in the sequence to splice in
  263. * @param elem The name of the element struct
  264. * @param link The name of the APR_RING_ENTRY in the element struct
  265. */
  266. #define APR_RING_SPLICE_HEAD(hp, ep1, epN, elem, link) do { \
  267. APR_RING_PREV((ep1), link) = APR_RING_SENTINEL((hp), elem, link);\
  268. APR_RING_NEXT((epN), link) = APR_RING_FIRST((hp)); \
  269. APR_RING_PREV(APR_RING_FIRST((hp)), link) = (epN); \
  270. APR_RING_FIRST((hp)) = (ep1); \
  271. } while (0)
  272. /**
  273. * Splice the sequence ep1..epN into the ring after the last element
  274. * (..hp.. becomes ..ep1..epN..hp..)
  275. * @param hp Head of the ring
  276. * @param ep1 First element in the sequence to splice in
  277. * @param epN Last element in the sequence to splice in
  278. * @param elem The name of the element struct
  279. * @param link The name of the APR_RING_ENTRY in the element struct
  280. */
  281. #define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link) do { \
  282. APR_RING_NEXT((epN), link) = APR_RING_SENTINEL((hp), elem, link);\
  283. APR_RING_PREV((ep1), link) = APR_RING_LAST((hp)); \
  284. APR_RING_NEXT(APR_RING_LAST((hp)), link) = (ep1); \
  285. APR_RING_LAST((hp)) = (epN); \
  286. } while (0)
  287. /**
  288. * Insert the element nep into the ring before the first element
  289. * (..hp.. becomes ..hp..nep..)
  290. * @param hp Head of the ring
  291. * @param nep Element to insert
  292. * @param elem The name of the element struct
  293. * @param link The name of the APR_RING_ENTRY in the element struct
  294. */
  295. #define APR_RING_INSERT_HEAD(hp, nep, elem, link) \
  296. APR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link)
  297. /**
  298. * Insert the element nep into the ring after the last element
  299. * (..hp.. becomes ..nep..hp..)
  300. * @param hp Head of the ring
  301. * @param nep Element to insert
  302. * @param elem The name of the element struct
  303. * @param link The name of the APR_RING_ENTRY in the element struct
  304. */
  305. #define APR_RING_INSERT_TAIL(hp, nep, elem, link) \
  306. APR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
  307. /**
  308. * Concatenate ring h2 onto the end of ring h1, leaving h2 empty.
  309. * @param h1 Head of the ring to concatenate onto
  310. * @param h2 Head of the ring to concatenate
  311. * @param elem The name of the element struct
  312. * @param link The name of the APR_RING_ENTRY in the element struct
  313. */
  314. #define APR_RING_CONCAT(h1, h2, elem, link) do { \
  315. if (!APR_RING_EMPTY((h2), elem, link)) { \
  316. APR_RING_SPLICE_TAIL((h1), APR_RING_FIRST((h2)), \
  317. APR_RING_LAST((h2)), elem, link); \
  318. APR_RING_INIT((h2), elem, link); \
  319. } \
  320. } while (0)
  321. /**
  322. * Prepend ring h2 onto the beginning of ring h1, leaving h2 empty.
  323. * @param h1 Head of the ring to prepend onto
  324. * @param h2 Head of the ring to prepend
  325. * @param elem The name of the element struct
  326. * @param link The name of the APR_RING_ENTRY in the element struct
  327. */
  328. #define APR_RING_PREPEND(h1, h2, elem, link) do { \
  329. if (!APR_RING_EMPTY((h2), elem, link)) { \
  330. APR_RING_SPLICE_HEAD((h1), APR_RING_FIRST((h2)), \
  331. APR_RING_LAST((h2)), elem, link); \
  332. APR_RING_INIT((h2), elem, link); \
  333. } \
  334. } while (0)
  335. /**
  336. * Unsplice a sequence of elements from a ring
  337. * @warning The unspliced sequence is left with dangling pointers at either end
  338. * @param ep1 First element in the sequence to unsplice
  339. * @param epN Last element in the sequence to unsplice
  340. * @param link The name of the APR_RING_ENTRY in the element struct
  341. */
  342. #define APR_RING_UNSPLICE(ep1, epN, link) do { \
  343. APR_RING_NEXT(APR_RING_PREV((ep1), link), link) = \
  344. APR_RING_NEXT((epN), link); \
  345. APR_RING_PREV(APR_RING_NEXT((epN), link), link) = \
  346. APR_RING_PREV((ep1), link); \
  347. } while (0)
  348. /**
  349. * Remove a single element from a ring
  350. * @warning The unspliced element is left with dangling pointers at either end
  351. * @param ep Element to remove
  352. * @param link The name of the APR_RING_ENTRY in the element struct
  353. */
  354. #define APR_RING_REMOVE(ep, link) \
  355. APR_RING_UNSPLICE((ep), (ep), link)
  356. /**
  357. * Iterate over a ring
  358. * @param ep The current element
  359. * @param head The head of the ring
  360. * @param elem The name of the element struct
  361. * @param link The name of the APR_RING_ENTRY in the element struct
  362. */
  363. #define APR_RING_FOREACH(ep, head, elem, link) \
  364. for (ep = APR_RING_FIRST(head); \
  365. ep != APR_RING_SENTINEL(head, elem, link); \
  366. ep = APR_RING_NEXT(ep, link))
  367. /**
  368. * Iterate over a ring safe against removal of the current element
  369. * @param ep1 The current element
  370. * @param ep2 Iteration cursor
  371. * @param head The head of the ring
  372. * @param elem The name of the element struct
  373. * @param link The name of the APR_RING_ENTRY in the element struct
  374. */
  375. #define APR_RING_FOREACH_SAFE(ep1, ep2, head, elem, link) \
  376. for (ep1 = APR_RING_FIRST(head), ep2 = APR_RING_NEXT(ep1, link); \
  377. ep1 != APR_RING_SENTINEL(head, elem, link); \
  378. ep1 = ep2, ep2 = APR_RING_NEXT(ep1, link))
  379. /* Debugging tools: */
  380. #ifdef APR_RING_DEBUG
  381. #include <stdio.h>
  382. #include <assert.h>
  383. #define APR_RING_CHECK_ONE(msg, ptr) \
  384. fprintf(stderr, "*** %s %p\n", msg, ptr)
  385. #define APR_RING_CHECK(hp, elem, link, msg) \
  386. APR_RING_CHECK_ELEM(APR_RING_SENTINEL(hp, elem, link), elem, link, msg)
  387. #define APR_RING_CHECK_ELEM(ep, elem, link, msg) do { \
  388. struct elem *start = (ep); \
  389. struct elem *here = start; \
  390. fprintf(stderr, "*** ring check start -- %s\n", msg); \
  391. do { \
  392. fprintf(stderr, "\telem %p\n", here); \
  393. fprintf(stderr, "\telem->next %p\n", \
  394. APR_RING_NEXT(here, link)); \
  395. fprintf(stderr, "\telem->prev %p\n", \
  396. APR_RING_PREV(here, link)); \
  397. fprintf(stderr, "\telem->next->prev %p\n", \
  398. APR_RING_PREV(APR_RING_NEXT(here, link), link)); \
  399. fprintf(stderr, "\telem->prev->next %p\n", \
  400. APR_RING_NEXT(APR_RING_PREV(here, link), link)); \
  401. if (APR_RING_PREV(APR_RING_NEXT(here, link), link) != here) { \
  402. fprintf(stderr, "\t*** elem->next->prev != elem\n"); \
  403. break; \
  404. } \
  405. if (APR_RING_NEXT(APR_RING_PREV(here, link), link) != here) { \
  406. fprintf(stderr, "\t*** elem->prev->next != elem\n"); \
  407. break; \
  408. } \
  409. here = APR_RING_NEXT(here, link); \
  410. } while (here != start); \
  411. fprintf(stderr, "*** ring check end\n"); \
  412. } while (0)
  413. #define APR_RING_CHECK_CONSISTENCY(hp, elem, link) \
  414. APR_RING_CHECK_ELEM_CONSISTENCY(APR_RING_SENTINEL(hp, elem, link),\
  415. elem, link)
  416. #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) do { \
  417. struct elem *start = (ep); \
  418. struct elem *here = start; \
  419. do { \
  420. assert(APR_RING_PREV(APR_RING_NEXT(here, link), link) == here); \
  421. assert(APR_RING_NEXT(APR_RING_PREV(here, link), link) == here); \
  422. here = APR_RING_NEXT(here, link); \
  423. } while (here != start); \
  424. } while (0)
  425. #else
  426. /**
  427. * Print a single pointer value to STDERR
  428. * (This is a no-op unless APR_RING_DEBUG is defined.)
  429. * @param msg Descriptive message
  430. * @param ptr Pointer value to print
  431. */
  432. #define APR_RING_CHECK_ONE(msg, ptr)
  433. /**
  434. * Dump all ring pointers to STDERR, starting with the head and looping all
  435. * the way around the ring back to the head. Aborts if an inconsistency
  436. * is found.
  437. * (This is a no-op unless APR_RING_DEBUG is defined.)
  438. * @param hp Head of the ring
  439. * @param elem The name of the element struct
  440. * @param link The name of the APR_RING_ENTRY in the element struct
  441. * @param msg Descriptive message
  442. */
  443. #define APR_RING_CHECK(hp, elem, link, msg)
  444. /**
  445. * Loops around a ring and checks all the pointers for consistency. Pops
  446. * an assertion if any inconsistency is found. Same idea as APR_RING_CHECK()
  447. * except that it's silent if all is well.
  448. * (This is a no-op unless APR_RING_DEBUG is defined.)
  449. * @param hp Head of the ring
  450. * @param elem The name of the element struct
  451. * @param link The name of the APR_RING_ENTRY in the element struct
  452. */
  453. #define APR_RING_CHECK_CONSISTENCY(hp, elem, link)
  454. /**
  455. * Dump all ring pointers to STDERR, starting with the given element and
  456. * looping all the way around the ring back to that element. Aborts if
  457. * an inconsistency is found.
  458. * (This is a no-op unless APR_RING_DEBUG is defined.)
  459. * @param ep The element
  460. * @param elem The name of the element struct
  461. * @param link The name of the APR_RING_ENTRY in the element struct
  462. * @param msg Descriptive message
  463. */
  464. #define APR_RING_CHECK_ELEM(ep, elem, link, msg)
  465. /**
  466. * Loops around a ring, starting with the given element, and checks all
  467. * the pointers for consistency. Pops an assertion if any inconsistency
  468. * is found. Same idea as APR_RING_CHECK_ELEM() except that it's silent
  469. * if all is well.
  470. * (This is a no-op unless APR_RING_DEBUG is defined.)
  471. * @param ep The element
  472. * @param elem The name of the element struct
  473. * @param link The name of the APR_RING_ENTRY in the element struct
  474. */
  475. #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link)
  476. #endif
  477. /** @} */
  478. #endif /* !APR_RING_H */