Advertisement
Guest User

Untitled

a guest
Mar 24th, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.66 KB | None | 0 0
  1. // Queue implemented by circularly-linked list.
  2. //
  3. // Adapted from libuv.
  4. //
  5. // Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
  6. //
  7. // Permission to use, copy, modify, and/or distribute this software for any
  8. // purpose with or without fee is hereby granted, provided that the above
  9. // copyright notice and this permission notice appear in all copies.
  10. //
  11. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18.  
  19. #ifndef QUEUE_H_
  20. #define QUEUE_H_
  21.  
  22. #include <stddef.h>
  23.  
  24. typedef void *QUEUE[2]; // QUEUE[0] -> next, QUEUE[1] -> prev
  25.  
  26. #define QUEUE_DATA(ptr, type, field) \
  27. ((type *) ((char *) (ptr) - offsetof(type, field)))
  28.  
  29. #define QUEUE_FOREACH(q, h) \
  30. for ((q) = (*(h))[0]; (q) != (h); (q) = (*(q))[0])
  31.  
  32. static inline int QUEUE_EMPTY(const QUEUE * const q)
  33. {
  34. return q == (*q)[0]; // q == q->next
  35. }
  36.  
  37. static inline QUEUE* QUEUE_HEAD(const QUEUE * const q)
  38. {
  39. return (*q)[0]; // q->next
  40. }
  41.  
  42. static inline QUEUE* QUEUE_TAIL(const QUEUE * const q)
  43. {
  44. return (*q)[1]; // q->prev
  45. }
  46.  
  47. static inline void QUEUE_INIT(QUEUE * const q)
  48. {
  49. // QUEUE_NEXT(q) = (q)
  50. (*q)[0] = (q); // q->next = q
  51. // QUEUE_PREV(q) = (q)
  52. (*q)[1] = (q); // q->prev = q
  53. }
  54.  
  55.  
  56. // +----+---+ +------+-+------+
  57. // |tail|0:h|<->|1:tail|h|0:head|
  58. // +----+---+ +------+-+------+
  59. // +----+-----+ +--------+-+--------+ +---+------+
  60. // |n_tail|0:n|<->|1:n_tail|n|0:n_head|<->|1:n|n_head|
  61. // +----+-----+ +---------+-+-------+ +---+------+
  62. // ||
  63. // \||/
  64. // \/
  65. // +----+--------+ +------+------+ +------+---+ +--------+-+
  66. // |tail|0:n_head|<->|1:tail|n_head|...|n_tail|0:h|<->|1:n_tail|h|
  67. // +----+--------+ +------+------+ +------+---+ +--------+-+
  68. //
  69. static inline void QUEUE_ADD(QUEUE * const h, QUEUE * const n)
  70. {
  71. // QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n)
  72. (*(QUEUE *)(*h)[1])[0] = (*n)[0]; // h->prev->next(=tail->next) = n->next(=n_head)
  73. // QUEUE_NEXT_PREV(n) = QUEUE_PREV(h)
  74. (*(QUEUE *)(*n)[0])[1] = (*h)[1]; // n->next->prev(=n_head->prev) = h->prev(=tail)
  75. // QUEUE_PREV(h) = QUEUE_PREV(n)
  76. (*h)[1] = (*n)[1]; // h->prev = n->prev(=n_tail)
  77. // QUEUE_PREV_NEXT(h) = (h)
  78. (*(QUEUE *)(*h)[1])[0] = (h); // h->prev->next(=n_tail->next) = h
  79. }
  80.  
  81.  
  82. // +----+---+ +------+-+------+ +---+---+ +-----+-+
  83. // +-->|tail|0:h|<->|1:tail|h|0:head|...|q-1|0:q|<->|1:q-1|q|--+
  84. // | +----+---+ +------+-+------+ +---+---+ +-----+-+ |
  85. // +-----------------------------------------------------------+
  86. // +---+-+---+
  87. // |1:n|n|0:n|
  88. // +---+-+---+
  89. // ||
  90. // \||/
  91. // \/
  92. // +----+---+ +------+-+---+ +---+-+
  93. // |tail|0:n|<->|1:tail|n|0:q|<->|1:n|q|...
  94. // +----+---+ +------+-+---+ +---+-+
  95. // +---+---+ +-----+-+
  96. // |q-1|0:h|<->|1:q-1|h|...
  97. // +---+---+ +-----+-+
  98. //
  99. static inline void QUEUE_SPLIT(QUEUE * const h, QUEUE * const q, QUEUE * const n)
  100. {
  101. // QUEUE_PREV(n) = QUEUE_PREV(h)
  102. (*n)[1] = (*h)[1]; // n->prev = h->prev(=tail)
  103. // QUEUE_PREV_NETX(n) = (n)
  104. (*(QUEUE *)(*n)[1])[0] = (n); // n->prev->next(=tail->next) = n
  105. // QUEUE_NEXT(n) = (q)
  106. (*n)[0] = (q); // n->next = q
  107. // QUEUE_PREV(h) = QUEUE_PREV(q)
  108. (*h)[1] = (*q)[1]; // h->prev = q->prev(=(q - 1))
  109. // QUEUE_PREV_NEXT(h) = (h)
  110. (*(QUEUE *)(*h)[1])[0] = (h); // h->prev->next(=(q - 1)->next) = h
  111. // QUEUE_PREV(q) = (n)
  112. (*q)[1] = (n); // q->prev = n
  113. }
  114.  
  115.  
  116. // +----+---+ +------+-+------+ +---+----+
  117. // +-->|tail|0:h|<->|1:tail|h|0:head|<->|1:h|head|--+
  118. // | +----+---+ +------+-+------+ +---+----+ |
  119. // +------------------------------------------------+
  120. //
  121. // +---+-+---+
  122. // |1:n|n|0:n|
  123. // +---+-+---+
  124. // ||
  125. // \||/
  126. // \/
  127. // +---+-+---+
  128. // |1:h|h|0:h|
  129. // +---+-+---+
  130. //
  131. // +----+---+ +------+-+------+ +---+----+
  132. // +-->|tail|0:n|<->|1:tail|n|0:head|<->|1:n|head|--+
  133. // | +----+---+ +------+-+------+ +---+----+ |
  134. // +------------------------------------------------+
  135. //
  136. static inline void QUEUE_MOVE(QUEUE * const h, QUEUE * const n)
  137. {
  138. if (QUEUE_EMPTY(h)) {
  139. QUEUE_INIT(n);
  140. } else {
  141. QUEUE* q = QUEUE_HEAD(h);
  142. QUEUE_SPLIT(h, q, n);
  143. }
  144. }
  145.  
  146.  
  147. // +------+--------+ +---+----+
  148. // |1:tail|h|0:head|<->|1:h|head|
  149. // +------+--------+ +---+----+
  150. // +---+-+---+
  151. // |1:q|q|0:q|
  152. // +---+-+---+
  153. // ||
  154. // \||/
  155. // \/
  156. // +------+-+---+ +---+-+------+ +---+----+
  157. // |1:tail|h|0:q|<->|1:h|q|0:head|<->|1:q|head|
  158. // +------+-+---+ +---+-+------+ +---+----+
  159. //
  160. static inline void QUEUE_INSERT_HEAD(QUEUE * const h, QUEUE * const q)
  161. {
  162. // QUEUE_NEXT(q) = QUEUE_NEXT(h)
  163. (*q)[0] = (*h)[0]; // q->next = h->next(=head)
  164. // QUEUE_PREV(q) = (h)
  165. (*q)[1] = (h); // q->prev = h
  166. // QUEUE_NEXT_PREV(q) = (q)
  167. (*(QUEUE *)(*q)[0])[1] = (q); // q->prev->next(=head->prev) = q
  168. // QUEUE_NEXT(h) = (q)
  169. (*h)[0] = (q); // h->next = q
  170. }
  171.  
  172.  
  173. // +----+---+ +------+--------+
  174. // |tail|0:h|<->|1:tail|h|0:head|
  175. // +----+---+ +------+--------+
  176. // +---+-+---+
  177. // |1:q|q|0:q|
  178. // +---+-+---+
  179. // ||
  180. // \||/
  181. // \/
  182. // +----+---+ +------+-+---+ +---+-+------+
  183. // |tail|0:q|<->|1:tail|q|0:h|<->|1:q|h|0:head|
  184. // +----+---+ +------+-+---+ +---+-+------+
  185. //
  186. static inline void QUEUE_INSERT_TAIL(QUEUE * const h, QUEUE * const q)
  187. {
  188. // QUEUE_NEXT(q) = (h)
  189. (*q)[0] = (h); // q->next = h
  190. // QUEUE_PREV(q) = QUEUE_PREV(h)
  191. (*q)[1] = (*h)[1]; // q->prev = h->prev(=tail)
  192. // QUEUE_PREV_NEXT(q) = (q)
  193. (*(QUEUE *)(*q)[1])[0] = (q); // q->prev->next(=tail->next) = q
  194. // QUEUE_PREV(h) = (q);
  195. (*h)[1] = (q); // h->prev = q
  196. }
  197.  
  198.  
  199. // +----+---+ +------+-+------+ +---+----+
  200. // |prev|0:q|<->|1:prev|q|0:next|<->|1:q|next|
  201. // +----+---+ +------+-+------+ +---+----+
  202. // ||
  203. // \||/
  204. // \/
  205. // +----+---+--+ +------+----+
  206. // |prev|0:next|<->|1:prev|next|
  207. // +----+------+ +------+----+
  208. //
  209. static inline void QUEUE_REMOVE(QUEUE * const q)
  210. {
  211. // QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q)
  212. (*(QUEUE *)(*q)[1])[0] = (*q)[0]; // q->prev->next = q->next
  213. // QUEUE_NEXT_PREV(q) = QUEUE_PREV(q)
  214. (*(QUEUE *)(*q)[0])[1] = (*q)[1]; // q->next->prev = q->prev
  215. }
  216.  
  217. #endif /* QUEUE_H_ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement