00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef ISC_QUEUE_H
00029 #define ISC_QUEUE_H 1
00030 #include <isc/assertions.h>
00031 #include <isc/boolean.h>
00032 #include <isc/mutex.h>
00033
00034 #ifdef ISC_QUEUE_CHECKINIT
00035 #define ISC_QLINK_INSIST(x) ISC_INSIST(x)
00036 #else
00037 #define ISC_QLINK_INSIST(x) (void)0
00038 #endif
00039
00040 #define ISC_QLINK(type) struct { type *prev, *next; }
00041
00042 #define ISC_QLINK_INIT(elt, link) \
00043 do { \
00044 (elt)->link.next = (elt)->link.prev = (void *)(-1); \
00045 } while(0)
00046
00047 #define ISC_QLINK_LINKED(elt, link) ((void*)(elt)->link.next != (void*)(-1))
00048
00049 #define ISC_QUEUE(type) struct { \
00050 type *head, *tail; \
00051 isc_mutex_t headlock, taillock; \
00052 }
00053
00054 #define ISC_QUEUE_INIT(queue, link) \
00055 do { \
00056 (void) isc_mutex_init(&(queue).taillock); \
00057 (void) isc_mutex_init(&(queue).headlock); \
00058 (queue).tail = (queue).head = NULL; \
00059 } while (0)
00060
00061 #define ISC_QUEUE_EMPTY(queue) ISC_TF((queue).head == NULL)
00062
00063 #define ISC_QUEUE_DESTROY(queue) \
00064 do { \
00065 ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \
00066 (void) isc_mutex_destroy(&(queue).taillock); \
00067 (void) isc_mutex_destroy(&(queue).headlock); \
00068 } while (0)
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 #define ISC_QUEUE_PUSH(queue, elt, link) \
00097 do { \
00098 isc_boolean_t headlocked = ISC_FALSE; \
00099 ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \
00100 if ((queue).head == NULL) { \
00101 LOCK(&(queue).headlock); \
00102 headlocked = ISC_TRUE; \
00103 } \
00104 LOCK(&(queue).taillock); \
00105 if ((queue).tail == NULL && !headlocked) { \
00106 UNLOCK(&(queue).taillock); \
00107 LOCK(&(queue).headlock); \
00108 LOCK(&(queue).taillock); \
00109 headlocked = ISC_TRUE; \
00110 } \
00111 (elt)->link.prev = (queue).tail; \
00112 (elt)->link.next = NULL; \
00113 if ((queue).tail != NULL) \
00114 (queue).tail->link.next = (elt); \
00115 (queue).tail = (elt); \
00116 UNLOCK(&(queue).taillock); \
00117 if (headlocked) { \
00118 if ((queue).head == NULL) \
00119 (queue).head = (elt); \
00120 UNLOCK(&(queue).headlock); \
00121 } \
00122 } while (0)
00123
00124 #define ISC_QUEUE_POP(queue, link, ret) \
00125 do { \
00126 LOCK(&(queue).headlock); \
00127 ret = (queue).head; \
00128 while (ret != NULL) { \
00129 if (ret->link.next == NULL) { \
00130 LOCK(&(queue).taillock); \
00131 if (ret->link.next == NULL) { \
00132 (queue).head = (queue).tail = NULL; \
00133 UNLOCK(&(queue).taillock); \
00134 break; \
00135 }\
00136 UNLOCK(&(queue).taillock); \
00137 } \
00138 (queue).head = ret->link.next; \
00139 (queue).head->link.prev = NULL; \
00140 break; \
00141 } \
00142 UNLOCK(&(queue).headlock); \
00143 if (ret != NULL) \
00144 (ret)->link.next = (ret)->link.prev = (void *)(-1); \
00145 } while(0)
00146
00147 #define ISC_QUEUE_UNLINK(queue, elt, link) \
00148 do { \
00149 ISC_QLINK_INSIST(ISC_QLINK_LINKED(elt, link)); \
00150 LOCK(&(queue).headlock); \
00151 LOCK(&(queue).taillock); \
00152 if ((elt)->link.prev == NULL) \
00153 (queue).head = (elt)->link.next; \
00154 else \
00155 (elt)->link.prev->link.next = (elt)->link.next; \
00156 if ((elt)->link.next == NULL) \
00157 (queue).tail = (elt)->link.prev; \
00158 else \
00159 (elt)->link.next->link.prev = (elt)->link.prev; \
00160 UNLOCK(&(queue).taillock); \
00161 UNLOCK(&(queue).headlock); \
00162 (elt)->link.next = (elt)->link.prev = (void *)(-1); \
00163 } while(0)
00164
00165 #endif