Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

apr_ring.h

Go to the documentation of this file.
00001 /* Copyright 2000-2004 The Apache Software Foundation
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  */
00015 
00016 /*
00017  * This code draws heavily from the 4.4BSD <sys/queue.h> macros
00018  * and Dean Gaudet's "splim/ring.h".
00019  * <http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h>
00020  * <http://www.arctic.org/~dean/splim/>
00021  *
00022  * We'd use Dean's code directly if we could guarantee the
00023  * availability of inline functions.
00024  */
00025 
00026 #ifndef APR_RING_H
00027 #define APR_RING_H
00028 
00034 /*
00035  * for offsetof()
00036  */
00037 #include "apr_general.h"
00038 
00069 #define APR_RING_ENTRY(elem)                                            \
00070     struct {                                                            \
00071         struct elem *next;                                              \
00072         struct elem *prev;                                              \
00073     }
00074 
00090 #define APR_RING_HEAD(head, elem)                                       \
00091     struct head {                                                       \
00092         struct elem *next;                                              \
00093         struct elem *prev;                                              \
00094     }
00095 
00158 #define APR_RING_SENTINEL(hp, elem, link)                               \
00159     (struct elem *)((char *)(hp) - APR_OFFSETOF(struct elem, link))
00160 
00165 #define APR_RING_FIRST(hp)      (hp)->next
00166 
00170 #define APR_RING_LAST(hp)       (hp)->prev
00171 
00176 #define APR_RING_NEXT(ep, link) (ep)->link.next
00177 
00182 #define APR_RING_PREV(ep, link) (ep)->link.prev
00183 
00184 
00191 #define APR_RING_INIT(hp, elem, link) do {                              \
00192         APR_RING_FIRST((hp)) = APR_RING_SENTINEL((hp), elem, link);     \
00193         APR_RING_LAST((hp))  = APR_RING_SENTINEL((hp), elem, link);     \
00194     } while (0)
00195 
00203 #define APR_RING_EMPTY(hp, elem, link)                                  \
00204     (APR_RING_FIRST((hp)) == APR_RING_SENTINEL((hp), elem, link))
00205 
00211 #define APR_RING_ELEM_INIT(ep, link) do {                               \
00212         APR_RING_NEXT((ep), link) = (ep);                               \
00213         APR_RING_PREV((ep), link) = (ep);                               \
00214     } while (0)
00215 
00216 
00227 #define APR_RING_SPLICE_BEFORE(lep, ep1, epN, link) do {                \
00228         APR_RING_NEXT((epN), link) = (lep);                             \
00229         APR_RING_PREV((ep1), link) = APR_RING_PREV((lep), link);        \
00230         APR_RING_NEXT(APR_RING_PREV((lep), link), link) = (ep1);        \
00231         APR_RING_PREV((lep), link) = (epN);                             \
00232     } while (0)
00233 
00244 #define APR_RING_SPLICE_AFTER(lep, ep1, epN, link) do {                 \
00245         APR_RING_PREV((ep1), link) = (lep);                             \
00246         APR_RING_NEXT((epN), link) = APR_RING_NEXT((lep), link);        \
00247         APR_RING_PREV(APR_RING_NEXT((lep), link), link) = (epN);        \
00248         APR_RING_NEXT((lep), link) = (ep1);                             \
00249     } while (0)
00250 
00260 #define APR_RING_INSERT_BEFORE(lep, nep, link)                          \
00261         APR_RING_SPLICE_BEFORE((lep), (nep), (nep), link)
00262 
00272 #define APR_RING_INSERT_AFTER(lep, nep, link)                           \
00273         APR_RING_SPLICE_AFTER((lep), (nep), (nep), link)
00274 
00275 
00285 #define APR_RING_SPLICE_HEAD(hp, ep1, epN, elem, link)                  \
00286         APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((hp), elem, link),      \
00287                              (ep1), (epN), link)
00288 
00298 #define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link)                  \
00299         APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((hp), elem, link),     \
00300                              (ep1), (epN), link)
00301 
00310 #define APR_RING_INSERT_HEAD(hp, nep, elem, link)                       \
00311         APR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link)
00312 
00321 #define APR_RING_INSERT_TAIL(hp, nep, elem, link)                       \
00322         APR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link)
00323 
00331 #define APR_RING_CONCAT(h1, h2, elem, link) do {                        \
00332         if (!APR_RING_EMPTY((h2), elem, link)) {                        \
00333             APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((h1), elem, link), \
00334                                   APR_RING_FIRST((h2)),                 \
00335                                   APR_RING_LAST((h2)), link);           \
00336             APR_RING_INIT((h2), elem, link);                            \
00337         }                                                               \
00338     } while (0)
00339 
00347 #define APR_RING_PREPEND(h1, h2, elem, link) do {                       \
00348         if (!APR_RING_EMPTY((h2), elem, link)) {                        \
00349             APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((h1), elem, link),  \
00350                                   APR_RING_FIRST((h2)),                 \
00351                                   APR_RING_LAST((h2)), link);           \
00352             APR_RING_INIT((h2), elem, link);                            \
00353         }                                                               \
00354     } while (0)
00355 
00363 #define APR_RING_UNSPLICE(ep1, epN, link) do {                          \
00364         APR_RING_NEXT(APR_RING_PREV((ep1), link), link) =               \
00365                      APR_RING_NEXT((epN), link);                        \
00366         APR_RING_PREV(APR_RING_NEXT((epN), link), link) =               \
00367                      APR_RING_PREV((ep1), link);                        \
00368     } while (0)
00369 
00376 #define APR_RING_REMOVE(ep, link)                                       \
00377     APR_RING_UNSPLICE((ep), (ep), link)
00378 
00379 
00423 #define APR_RING_FOREACH(ep, hp, elem, link)                            \
00424     for ((ep)  = APR_RING_FIRST((hp));                                  \
00425          (ep) != APR_RING_SENTINEL((hp), elem, link);                   \
00426          (ep)  = APR_RING_NEXT((ep), link))
00427 
00436 #define APR_RING_FOREACH_REVERSE(ep, hp, elem, link)                    \
00437     for ((ep)  = APR_RING_LAST((hp));                                   \
00438          (ep) != APR_RING_SENTINEL((hp), elem, link);                   \
00439          (ep)  = APR_RING_PREV((ep), link))
00440 
00441 
00442 /* Debugging tools: */
00443 
00444 #ifdef APR_RING_DEBUG
00445 #include <stdio.h>
00446 #include <assert.h>
00447 
00448 #define APR_RING_CHECK_ONE(msg, ptr)                                    \
00449         fprintf(stderr, "*** %s %p\n", msg, ptr)
00450 
00451 #define APR_RING_CHECK(hp, elem, link, msg)                             \
00452         APR_RING_CHECK_ELEM(APR_RING_SENTINEL(hp, elem, link), elem, link, msg)
00453 
00454 #define APR_RING_CHECK_ELEM(ep, elem, link, msg) do {                   \
00455         struct elem *start = (ep);                                      \
00456         struct elem *here = start;                                      \
00457         fprintf(stderr, "*** ring check start -- %s\n", msg);           \
00458         do {                                                            \
00459             fprintf(stderr, "\telem %p\n", here);                       \
00460             fprintf(stderr, "\telem->next %p\n",                        \
00461                     APR_RING_NEXT(here, link));                         \
00462             fprintf(stderr, "\telem->prev %p\n",                        \
00463                     APR_RING_PREV(here, link));                         \
00464             fprintf(stderr, "\telem->next->prev %p\n",                  \
00465                     APR_RING_PREV(APR_RING_NEXT(here, link), link));    \
00466             fprintf(stderr, "\telem->prev->next %p\n",                  \
00467                     APR_RING_NEXT(APR_RING_PREV(here, link), link));    \
00468             if (APR_RING_PREV(APR_RING_NEXT(here, link), link) != here) { \
00469                 fprintf(stderr, "\t*** elem->next->prev != elem\n");    \
00470                 break;                                                  \
00471             }                                                           \
00472             if (APR_RING_NEXT(APR_RING_PREV(here, link), link) != here) { \
00473                 fprintf(stderr, "\t*** elem->prev->next != elem\n");    \
00474                 break;                                                  \
00475             }                                                           \
00476             here = APR_RING_NEXT(here, link);                           \
00477         } while (here != start);                                        \
00478         fprintf(stderr, "*** ring check end\n");                        \
00479     } while (0)
00480 
00481 #define APR_RING_CHECK_CONSISTENCY(hp, elem, link)                      \
00482         APR_RING_CHECK_ELEM_CONSISTENCY(APR_RING_SENTINEL(hp, elem, link),\
00483                                         elem, link)
00484 
00485 #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) do {            \
00486         struct elem *start = (ep);                                      \
00487         struct elem *here = start;                                      \
00488         do {                                                            \
00489             assert(APR_RING_PREV(APR_RING_NEXT(here, link), link) == here); \
00490             assert(APR_RING_NEXT(APR_RING_PREV(here, link), link) == here); \
00491             here = APR_RING_NEXT(here, link);                           \
00492         } while (here != start);                                        \
00493     } while (0)
00494 
00495 #else
00496 
00502 #define APR_RING_CHECK_ONE(msg, ptr)
00503 
00513 #define APR_RING_CHECK(hp, elem, link, msg)
00514 
00523 #define APR_RING_CHECK_CONSISTENCY(hp, elem, link)
00524 
00534 #define APR_RING_CHECK_ELEM(ep, elem, link, msg)
00535 
00545 #define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link)
00546 #endif
00547 
00550 #endif /* !APR_RING_H */

Generated on Wed Dec 8 10:14:03 2004 for Apache Portable Runtime by doxygen 1.3.6