Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

shqueue.h

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: shqueue.h,v 12.2 2005/08/12 13:17:21 bostic Exp $
00008  */
00009 
00010 #ifndef _SYS_SHQUEUE_H_
00011 #define _SYS_SHQUEUE_H_
00012 
00013 /*
00014  * This file defines two types of data structures: lists and tail queues
00015  * similarly to the include file <sys/queue.h>.
00016  *
00017  * The difference is that this set of macros can be used for structures that
00018  * reside in shared memory that may be mapped at different addresses in each
00019  * process.  In most cases, the macros for shared structures exactly mirror
00020  * the normal macros, although the macro calls require an additional type
00021  * parameter, only used by the HEAD and ENTRY macros of the standard macros.
00022  *
00023  * Since we use relative offsets of type ssize_t rather than pointers, 0
00024  * (aka NULL) is a valid offset and cannot be used to indicate the end
00025  * of a list.  Therefore, we use -1 to indicate end of list.
00026  *
00027  * The macros ending in "P" return pointers without checking for end or
00028  * beginning of lists, the others check for end of list and evaluate to
00029  * either a pointer or NULL.
00030  *
00031  * For details on the use of these macros, see the queue(3) manual page.
00032  */
00033 
00034 #if defined(__cplusplus)
00035 extern "C" {
00036 #endif
00037 
00038 /*
00039  * Shared memory list definitions.
00040  */
00041 #define SH_LIST_HEAD(name)                                              \
00042 struct name {                                                           \
00043         ssize_t slh_first;      /* first element */                     \
00044 }
00045 
00046 #define SH_LIST_HEAD_INITIALIZER(head)                                  \
00047         { -1 }
00048 
00049 #define SH_LIST_ENTRY                                                   \
00050 struct {                                                                \
00051         ssize_t sle_next;       /* relative offset to next element */   \
00052         ssize_t sle_prev;       /* relative offset of prev element */   \
00053 }
00054 
00055 /*
00056  * Shared memory list functions.
00057  */
00058 
00059 #define SH_LIST_EMPTY(head)                                             \
00060         ((head)->slh_first == -1)
00061 
00062 #define SH_LIST_FIRSTP(head, type)                                      \
00063         ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))
00064 
00065 #define SH_LIST_FIRST(head, type)                                       \
00066         (SH_LIST_EMPTY(head) ? NULL :                                   \
00067         ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)))
00068 
00069 #define SH_LIST_NEXTP(elm, field, type)                                 \
00070         ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))
00071 
00072 #define SH_LIST_NEXT(elm, field, type)                                  \
00073         ((elm)->field.sle_next == -1 ? NULL :                           \
00074         ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)))
00075 
00076   /*
00077    *__SH_LIST_PREV_OFF is private API.  It calculates the address of
00078    * the elm->field.sle_next member of a SH_LIST structure.  All offsets
00079    * between elements are relative to that point in SH_LIST structures.
00080    */
00081 #define __SH_LIST_PREV_OFF(elm, field)                                  \
00082         ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev))
00083 
00084 #define SH_LIST_PREV(elm, field, type)                                  \
00085         (struct type *)((ssize_t)elm - (*__SH_LIST_PREV_OFF(elm, field)))
00086 
00087 #define SH_LIST_FOREACH(var, head, field, type)                         \
00088         for ((var) = SH_LIST_FIRST((head), type);                       \
00089             (var);                                                      \
00090             (var) = SH_LIST_NEXT((var), field, type))
00091 
00092 #define SH_PTR_TO_OFF(src, dest)                                        \
00093         ((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src))))
00094 
00095 /*
00096  * Given correct A.next: B.prev = SH_LIST_NEXT_TO_PREV(A)
00097  * in a list [A, B]
00098  * The prev value is always the offset from an element to its preceding
00099  * element's next location, not the beginning of the structure.  To get
00100  * to the beginning of an element structure in memory given an element
00101  * do the following:
00102  * A = B - (B.prev + (&B.next - B))
00103  * Take the element's next pointer and calculate what the corresponding
00104  * Prev pointer should be -- basically it is the negation plus the offset
00105  * of the next field in the structure.
00106  */
00107 #define SH_LIST_NEXT_TO_PREV(elm, field)                                \
00108         (((elm)->field.sle_next == -1 ? 0 : -(elm)->field.sle_next) +   \
00109            SH_PTR_TO_OFF(elm, &(elm)->field.sle_next))
00110 
00111 #define SH_LIST_INIT(head) (head)->slh_first = -1
00112 
00113 #define SH_LIST_INSERT_BEFORE(head, listelm, elm, field, type) do {     \
00114         if (listelm == SH_LIST_FIRST(head, type)) {                     \
00115         SH_LIST_INSERT_HEAD(head, elm, field, type);                    \
00116         } else {                                                        \
00117                 (elm)->field.sle_next = SH_PTR_TO_OFF(elm, listelm);    \
00118                 (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(           \
00119                         SH_LIST_PREV((listelm), field, type), field) +  \
00120                 (elm)->field.sle_next;                                  \
00121                 (SH_LIST_PREV(listelm, field, type))->field.sle_next =  \
00122                         (SH_PTR_TO_OFF((SH_LIST_PREV(listelm, field,    \
00123                                                      type)), elm));     \
00124         (listelm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(elm, field);   \
00125         }                                                               \
00126 } while (0)
00127 
00128 #define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do {            \
00129         if ((listelm)->field.sle_next != -1) {                          \
00130                 (elm)->field.sle_next = SH_PTR_TO_OFF(elm,              \
00131                     SH_LIST_NEXTP(listelm, field, type));               \
00132                 SH_LIST_NEXTP(listelm, field, type)->field.sle_prev =   \
00133                         SH_LIST_NEXT_TO_PREV(elm, field);               \
00134         } else                                                          \
00135                 (elm)->field.sle_next = -1;                             \
00136         (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm);        \
00137         (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field);   \
00138 } while (0)
00139 
00140 #define SH_LIST_INSERT_HEAD(head, elm, field, type) do {                \
00141         if ((head)->slh_first != -1) {                                  \
00142                 (elm)->field.sle_next =                                 \
00143                     (head)->slh_first - SH_PTR_TO_OFF(head, elm);       \
00144                 SH_LIST_FIRSTP(head, type)->field.sle_prev =            \
00145                         SH_LIST_NEXT_TO_PREV(elm, field);               \
00146         } else                                                          \
00147                 (elm)->field.sle_next = -1;                             \
00148         (head)->slh_first = SH_PTR_TO_OFF(head, elm);                   \
00149         (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \
00150 } while (0)
00151 
00152 #define SH_LIST_REMOVE(elm, field, type) do {                           \
00153         if ((elm)->field.sle_next != -1) {                              \
00154                 SH_LIST_NEXTP(elm, field, type)->field.sle_prev =       \
00155                         (elm)->field.sle_prev - (elm)->field.sle_next;  \
00156                 *__SH_LIST_PREV_OFF(elm, field) += (elm)->field.sle_next;\
00157         } else                                                          \
00158                 *__SH_LIST_PREV_OFF(elm, field) = -1;                   \
00159 } while (0)
00160 
00161 #define SH_LIST_REMOVE_HEAD(head, field, type) do {                     \
00162         if (!SH_LIST_EMPTY(head)) {                                     \
00163                 SH_LIST_REMOVE(SH_LIST_FIRSTP(head, type), field, type);\
00164         }                                                               \
00165 } while (0)
00166 
00167 /*
00168  * Shared memory tail queue definitions.
00169  */
00170 #define SH_TAILQ_HEAD(name)                                             \
00171 struct name {                                                           \
00172         ssize_t stqh_first;     /* relative offset of first element */  \
00173         ssize_t stqh_last;      /* relative offset of last's next */    \
00174 }
00175 
00176 #define SH_TAILQ_HEAD_INITIALIZER(head)                                 \
00177         { -1, 0 }
00178 
00179 #define SH_TAILQ_ENTRY                                                  \
00180 struct {                                                                \
00181         ssize_t stqe_next;      /* relative offset of next element */   \
00182         ssize_t stqe_prev;      /* relative offset of prev's next */    \
00183 }
00184 
00185 /*
00186  * Shared memory tail queue functions.
00187  */
00188 
00189 #define SH_TAILQ_EMPTY(head)                                            \
00190         ((head)->stqh_first == -1)
00191 
00192 #define SH_TAILQ_FIRSTP(head, type)                                     \
00193         ((struct type *)((u_int8_t *)(head) + (head)->stqh_first))
00194 
00195 #define SH_TAILQ_FIRST(head, type)                                      \
00196         (SH_TAILQ_EMPTY(head) ? NULL : SH_TAILQ_FIRSTP(head, type))
00197 
00198 #define SH_TAILQ_NEXTP(elm, field, type)                                \
00199         ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next))
00200 
00201 #define SH_TAILQ_NEXT(elm, field, type)                                 \
00202         ((elm)->field.stqe_next == -1 ? NULL :                          \
00203         ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next)))
00204 
00205   /*
00206    * __SH_TAILQ_PREV_OFF is private API.  It calculates the address of
00207    * the elm->field.stqe_next member of a SH_TAILQ structure.  All
00208    * offsets between elements are relative to that point in SH_TAILQ
00209    * structures.
00210    */
00211 #define __SH_TAILQ_PREV_OFF(elm, field)                                 \
00212         ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.stqe_prev))
00213 
00214 #define SH_TAILQ_PREVP(elm, field, type)                                \
00215         (struct type *)((ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field)))
00216 
00217 #define SH_TAILQ_PREV(head, elm, field, type)                           \
00218         (((elm) == SH_TAILQ_FIRST(head, type)) ? NULL :         \
00219           (struct type *)((ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field))))
00220 
00221   /*
00222    * __SH_TAILQ_LAST_OFF is private API.  It calculates the address of
00223    * the stqe_next member of a SH_TAILQ structure in the last element
00224    * of this list.  All offsets between elements are relative to that
00225    * point in SH_TAILQ structures.
00226    */
00227 #define __SH_TAILQ_LAST_OFF(head)                                       \
00228         ((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last))
00229 
00230 #define SH_TAILQ_LASTP(head, field, type)                               \
00231         ((struct type *)((ssize_t)(head) +                              \
00232          ((ssize_t)((head)->stqh_last) -                                \
00233          ((ssize_t)SH_PTR_TO_OFF(SH_TAILQ_FIRST(head, type),            \
00234                 &(SH_TAILQ_FIRSTP(head, type)->field.stqe_next))))))
00235 
00236 #define SH_TAILQ_LAST(head, field, type)                                \
00237         (SH_TAILQ_EMPTY(head) ? NULL : SH_TAILQ_LASTP(head, field, type))
00238 
00239 /*
00240  * Given correct A.next: B.prev = SH_TAILQ_NEXT_TO_PREV(A)
00241  * in a list [A, B]
00242  * The prev value is always the offset from an element to its preceding
00243  * element's next location, not the beginning of the structure.  To get
00244  * to the beginning of an element structure in memory given an element
00245  * do the following:
00246  * A = B - (B.prev + (&B.next - B))
00247  */
00248 #define SH_TAILQ_NEXT_TO_PREV(elm, field)                               \
00249         (((elm)->field.stqe_next == -1 ? 0 :                            \
00250                 (-(elm)->field.stqe_next) +                             \
00251                 SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next)))
00252 
00253 #define SH_TAILQ_FOREACH(var, head, field, type)                        \
00254         for ((var) = SH_TAILQ_FIRST((head), type);                      \
00255             (var);                                                      \
00256             (var) = SH_TAILQ_NEXT((var), field, type))
00257 
00258 #define SH_TAILQ_FOREACH_REVERSE(var, head, field, type)                \
00259         for ((var) = SH_TAILQ_LAST((head), field, type);                \
00260             (var);                                                      \
00261             (var) = SH_TAILQ_PREV((head), (var), field, type))
00262 
00263 #define SH_TAILQ_INIT(head) {                                           \
00264         (head)->stqh_first = -1;                                        \
00265         (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first);   \
00266 }
00267 
00268 #define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do {               \
00269         if ((head)->stqh_first != -1) {                                 \
00270                 (elm)->field.stqe_next =                                \
00271                     (head)->stqh_first - SH_PTR_TO_OFF(head, elm);      \
00272                 SH_TAILQ_FIRSTP(head, type)->field.stqe_prev =          \
00273                         SH_TAILQ_NEXT_TO_PREV(elm, field);              \
00274         } else {                                                        \
00275                 (head)->stqh_last =                                     \
00276                     SH_PTR_TO_OFF(head, &(elm)->field.stqe_next);       \
00277                 (elm)->field.stqe_next = -1;                            \
00278         }                                                               \
00279         (head)->stqh_first = SH_PTR_TO_OFF(head, elm);                  \
00280         (elm)->field.stqe_prev =                                        \
00281             SH_PTR_TO_OFF(elm, &(head)->stqh_first);                    \
00282 } while (0)
00283 
00284 #define SH_TAILQ_INSERT_TAIL(head, elm, field) do {                     \
00285         (elm)->field.stqe_next = -1;                                    \
00286         (elm)->field.stqe_prev =                                        \
00287             -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last;              \
00288         if ((head)->stqh_last ==                                        \
00289             SH_PTR_TO_OFF((head), &(head)->stqh_first))                 \
00290                 (head)->stqh_first = SH_PTR_TO_OFF(head, elm);          \
00291         else                                                            \
00292                 *__SH_TAILQ_LAST_OFF(head) = -(head)->stqh_last +       \
00293                     SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) +     \
00294                     SH_PTR_TO_OFF(head, elm);                           \
00295         (head)->stqh_last =                                             \
00296             SH_PTR_TO_OFF(head, &((elm)->field.stqe_next));             \
00297 } while (0)
00298 
00299 #define SH_TAILQ_INSERT_BEFORE(head, listelm, elm, field, type) do {    \
00300         if (listelm == SH_TAILQ_FIRST(head, type)) {                    \
00301                 SH_TAILQ_INSERT_HEAD(head, elm, field, type);           \
00302         } else {                                                        \
00303                 (elm)->field.stqe_next = SH_PTR_TO_OFF(elm, listelm);   \
00304                 (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(         \
00305                         SH_TAILQ_PREVP((listelm), field, type), field) + \
00306                         (elm)->field.stqe_next;                         \
00307                 (SH_TAILQ_PREVP(listelm, field, type))->field.stqe_next =\
00308                 (SH_PTR_TO_OFF((SH_TAILQ_PREVP(listelm, field, type)),  \
00309                         elm));                                          \
00310                 (listelm)->field.stqe_prev =                            \
00311                         SH_TAILQ_NEXT_TO_PREV(elm, field);              \
00312         }                                                               \
00313 } while (0)
00314 
00315 #define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do {     \
00316         if ((listelm)->field.stqe_next != -1) {                         \
00317                 (elm)->field.stqe_next = (listelm)->field.stqe_next -   \
00318                     SH_PTR_TO_OFF(listelm, elm);                        \
00319                 SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \
00320                     SH_TAILQ_NEXT_TO_PREV(elm, field);                  \
00321         } else {                                                        \
00322                 (elm)->field.stqe_next = -1;                            \
00323                 (head)->stqh_last =                                     \
00324                     SH_PTR_TO_OFF(head, &elm->field.stqe_next);         \
00325         }                                                               \
00326         (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm);       \
00327         (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \
00328 } while (0)
00329 
00330 #define SH_TAILQ_REMOVE(head, elm, field, type) do {                    \
00331         if ((elm)->field.stqe_next != -1) {                             \
00332                 SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev =     \
00333                     (elm)->field.stqe_prev +                            \
00334                     SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm,                   \
00335                     field, type), elm);                                 \
00336                 *__SH_TAILQ_PREV_OFF(elm, field) += elm->field.stqe_next;\
00337         } else {                                                        \
00338                 (head)->stqh_last = (elm)->field.stqe_prev +            \
00339                         SH_PTR_TO_OFF(head, elm);                       \
00340                 *__SH_TAILQ_PREV_OFF(elm, field) = -1;                  \
00341         }                                                               \
00342 } while (0)
00343 
00344 #if defined(__cplusplus)
00345 }
00346 #endif
00347 #endif  /* !_SYS_SHQUEUE_H_ */

Generated on Sun Dec 25 12:14:22 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2