2
0

fspr_ring.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 fspr_ring.h
  29. * @brief APR Rings
  30. */
  31. /*
  32. * for offsetof()
  33. */
  34. #include "fspr_general.h"
  35. /**
  36. * @defgroup fspr_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 *next; \
  67. struct elem *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 *next; \
  87. struct elem *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) - 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) \
  267. APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((hp), elem, link), \
  268. (ep1), (epN), link)
  269. /**
  270. * Splice the sequence ep1..epN into the ring after the last element
  271. * (..hp.. becomes ..ep1..epN..hp..)
  272. * @param hp Head of the ring
  273. * @param ep1 First element in the sequence to splice in
  274. * @param epN Last element in the sequence to splice in
  275. * @param elem The name of the element struct
  276. * @param link The name of the APR_RING_ENTRY in the element struct
  277. */
  278. #define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link) \
  279. APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((hp), elem, link), \
  280. (ep1), (epN), link)
  281. /**
  282. * Insert the element nep into the ring before the first element
  283. * (..hp.. becomes ..hp..nep..)
  284. * @param hp Head of the ring
  285. * @param nep Element to insert
  286. * @param elem The name of the element struct
  287. * @param link The name of the APR_RING_ENTRY in the element struct
  288. */
  289. #define APR_RING_INSERT_HEAD(hp, nep, elem, link) \
  290. APR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link)
  291. /**
  292. * Insert the element nep into the ring after the last element
  293. * (..hp.. becomes ..nep..hp..)
  294. * @param hp Head of the ring
  295. * @param nep Element to insert
  296. * @param elem The name of the element struct
  297. * @param link The name of the APR_RING_ENTRY in the element struct
  298. */
  299. #define APR_RING_INSERT_TAIL(hp, nep, elem, link) \
  300. APR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
  301. /**
  302. * Concatenate ring h2 onto the end of ring h1, leaving h2 empty.
  303. * @param h1 Head of the ring to concatenate onto
  304. * @param h2 Head of the ring to concatenate
  305. * @param elem The name of the element struct
  306. * @param link The name of the APR_RING_ENTRY in the element struct
  307. */
  308. #define APR_RING_CONCAT(h1, h2, elem, link) do { \
  309. if (!APR_RING_EMPTY((h2), elem, link)) { \
  310. APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((h1), elem, link), \
  311. APR_RING_FIRST((h2)), \
  312. APR_RING_LAST((h2)), link); \
  313. APR_RING_INIT((h2), elem, link); \
  314. } \
  315. } while (0)
  316. /**
  317. * Prepend ring h2 onto the beginning of ring h1, leaving h2 empty.
  318. * @param h1 Head of the ring to prepend onto
  319. * @param h2 Head of the ring to prepend
  320. * @param elem The name of the element struct
  321. * @param link The name of the APR_RING_ENTRY in the element struct
  322. */
  323. #define APR_RING_PREPEND(h1, h2, elem, link) do { \
  324. if (!APR_RING_EMPTY((h2), elem, link)) { \
  325. APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((h1), elem, link), \
  326. APR_RING_FIRST((h2)), \
  327. APR_RING_LAST((h2)), link); \
  328. APR_RING_INIT((h2), elem, link); \
  329. } \
  330. } while (0)
  331. /**
  332. * Unsplice a sequence of elements from a ring
  333. * @warning The unspliced sequence is left with dangling pointers at either end
  334. * @param ep1 First element in the sequence to unsplice
  335. * @param epN Last element in the sequence to unsplice
  336. * @param link The name of the APR_RING_ENTRY in the element struct
  337. */
  338. #define APR_RING_UNSPLICE(ep1, epN, link) do { \
  339. APR_RING_NEXT(APR_RING_PREV((ep1), link), link) = \
  340. APR_RING_NEXT((epN), link); \
  341. APR_RING_PREV(APR_RING_NEXT((epN), link), link) = \
  342. APR_RING_PREV((ep1), link); \
  343. } while (0)
  344. /**
  345. * Remove a single element from a ring
  346. * @warning The unspliced element is left with dangling pointers at either end
  347. * @param ep Element to remove
  348. * @param link The name of the APR_RING_ENTRY in the element struct
  349. */
  350. #define APR_RING_REMOVE(ep, link) \
  351. APR_RING_UNSPLICE((ep), (ep), link)
  352. /**
  353. * Iterate over a ring
  354. * @param ep The current element
  355. * @param head The head of the ring
  356. * @param elem The name of the element struct
  357. * @param link The name of the APR_RING_ENTRY in the element struct
  358. */
  359. #define APR_RING_FOREACH(ep, head, elem, link) \
  360. for (ep = APR_RING_FIRST(head); \
  361. ep != APR_RING_SENTINEL(head, elem, link); \
  362. ep = APR_RING_NEXT(ep, link))
  363. /**
  364. * Iterate over a ring safe against removal of the current element
  365. * @param ep1 The current element
  366. * @param ep2 Iteration cursor
  367. * @param head The head of the ring
  368. * @param elem The name of the element struct
  369. * @param link The name of the APR_RING_ENTRY in the element struct
  370. */
  371. #define APR_RING_FOREACH_SAFE(ep1, ep2, head, elem, link) \
  372. for (ep1 = APR_RING_FIRST(head), ep2 = APR_RING_NEXT(ep1, link); \
  373. ep1 != APR_RING_SENTINEL(head, elem, link); \
  374. ep1 = ep2, ep2 = APR_RING_NEXT(ep1, link))
  375. /* Debugging tools: */
  376. #ifdef APR_RING_DEBUG
  377. #include <stdio.h>
  378. #include <assert.h>
  379. #define APR_RING_CHECK_ONE(msg, ptr) \
  380. fprintf(stderr, "*** %s %p\n", msg, ptr)
  381. #define APR_RING_CHECK(hp, elem, link, msg) \
  382. APR_RING_CHECK_ELEM(APR_RING_SENTINEL(hp, elem, link), elem, link, msg)
  383. #define APR_RING_CHECK_ELEM(ep, elem, link, msg) do { \
  384. struct elem *start = (ep); \
  385. struct elem *here = start; \
  386. fprintf(stderr, "*** ring check start -- %s\n", msg); \
  387. do { \
  388. fprintf(stderr, "\telem %p\n", here); \
  389. fprintf(stderr, "\telem->next %p\n", \
  390. APR_RING_NEXT(here, link)); \
  391. fprintf(stderr, "\telem->prev %p\n", \
  392. APR_RING_PREV(here, link)); \
  393. fprintf(stderr, "\telem->next->prev %p\n", \
  394. APR_RING_PREV(APR_RING_NEXT(here, link), link)); \
  395. fprintf(stderr, "\telem->prev->next %p\n", \
  396. APR_RING_NEXT(APR_RING_PREV(here, link), link)); \
  397. if (APR_RING_PREV(APR_RING_NEXT(here, link), link) != here) { \
  398. fprintf(stderr, "\t*** elem->next->prev != elem\n"); \
  399. break; \
  400. } \
  401. if (APR_RING_NEXT(APR_RING_PREV(here, link), link) != here) { \
  402. fprintf(stderr, "\t*** elem->prev->next != elem\n"); \
  403. break; \
  404. } \
  405. here = APR_RING_NEXT(here, link); \
  406. } while (here != start); \
  407. fprintf(stderr, "*** ring check end\n"); \
  408. } while (0)
  409. #define APR_RING_CHECK_CONSISTENCY(hp, elem, link) \
  410. APR_RING_CHECK_ELEM_CONSISTENCY(APR_RING_SENTINEL(hp, elem, link),\
  411. elem, link)
  412. #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) do { \
  413. struct elem *start = (ep); \
  414. struct elem *here = start; \
  415. do { \
  416. assert(APR_RING_PREV(APR_RING_NEXT(here, link), link) == here); \
  417. assert(APR_RING_NEXT(APR_RING_PREV(here, link), link) == here); \
  418. here = APR_RING_NEXT(here, link); \
  419. } while (here != start); \
  420. } while (0)
  421. #else
  422. /**
  423. * Print a single pointer value to STDERR
  424. * (This is a no-op unless APR_RING_DEBUG is defined.)
  425. * @param msg Descriptive message
  426. * @param ptr Pointer value to print
  427. */
  428. #define APR_RING_CHECK_ONE(msg, ptr)
  429. /**
  430. * Dump all ring pointers to STDERR, starting with the head and looping all
  431. * the way around the ring back to the head. Aborts if an inconsistency
  432. * is found.
  433. * (This is a no-op unless APR_RING_DEBUG is defined.)
  434. * @param hp Head of the ring
  435. * @param elem The name of the element struct
  436. * @param link The name of the APR_RING_ENTRY in the element struct
  437. * @param msg Descriptive message
  438. */
  439. #define APR_RING_CHECK(hp, elem, link, msg)
  440. /**
  441. * Loops around a ring and checks all the pointers for consistency. Pops
  442. * an assertion if any inconsistency is found. Same idea as APR_RING_CHECK()
  443. * except that it's silent if all is well.
  444. * (This is a no-op unless APR_RING_DEBUG is defined.)
  445. * @param hp Head of the ring
  446. * @param elem The name of the element struct
  447. * @param link The name of the APR_RING_ENTRY in the element struct
  448. */
  449. #define APR_RING_CHECK_CONSISTENCY(hp, elem, link)
  450. /**
  451. * Dump all ring pointers to STDERR, starting with the given element and
  452. * looping all the way around the ring back to that element. Aborts if
  453. * an inconsistency is found.
  454. * (This is a no-op unless APR_RING_DEBUG is defined.)
  455. * @param ep The element
  456. * @param elem The name of the element struct
  457. * @param link The name of the APR_RING_ENTRY in the element struct
  458. * @param msg Descriptive message
  459. */
  460. #define APR_RING_CHECK_ELEM(ep, elem, link, msg)
  461. /**
  462. * Loops around a ring, starting with the given element, and checks all
  463. * the pointers for consistency. Pops an assertion if any inconsistency
  464. * is found. Same idea as APR_RING_CHECK_ELEM() except that it's silent
  465. * if all is well.
  466. * (This is a no-op unless APR_RING_DEBUG is defined.)
  467. * @param ep The element
  468. * @param elem The name of the element struct
  469. * @param link The name of the APR_RING_ENTRY in the element struct
  470. */
  471. #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link)
  472. #endif
  473. /** @} */
  474. #endif /* !APR_RING_H */