| 1 | // $Id: dplayx_queue.h,v 1.3 2000-10-06 19:49:06 hugh Exp $ | 
|---|
| 2 | /* A queue definition based on sys/queue.h TAILQ definitions | 
|---|
| 3 | * | 
|---|
| 4 | * Blame any implementation mistakes on Peter Hunnisett | 
|---|
| 5 | * <hunnise@nortelnetworks.com> | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #ifndef __WINE_DPLAYX_QUEUE_H | 
|---|
| 9 | #define __WINE_DPLAYX_QUEUE_H | 
|---|
| 10 |  | 
|---|
| 11 | #include "winbase.h" | 
|---|
| 12 |  | 
|---|
| 13 | #define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c) | 
|---|
| 14 |  | 
|---|
| 15 | /* | 
|---|
| 16 | * Tail queue definitions. | 
|---|
| 17 | */ | 
|---|
| 18 | #define DPQ_HEAD(type)                                           \ | 
|---|
| 19 | struct {                                                         \ | 
|---|
| 20 | struct type *lpQHFirst; /* first element */              \ | 
|---|
| 21 | struct type **lpQHLast; /* addr of last next element */  \ | 
|---|
| 22 | } | 
|---|
| 23 |  | 
|---|
| 24 | #define DPQ_ENTRY(type)                                               \ | 
|---|
| 25 | struct {                                                              \ | 
|---|
| 26 | struct type *lpQNext;  /* next element */                     \ | 
|---|
| 27 | struct type **lpQPrev; /* address of previous next element */ \ | 
|---|
| 28 | } | 
|---|
| 29 |  | 
|---|
| 30 | /* | 
|---|
| 31 | * Tail queue functions. | 
|---|
| 32 | */ | 
|---|
| 33 | #define DPQ_INIT(head)                       \ | 
|---|
| 34 | do{                                          \ | 
|---|
| 35 | (head).lpQHFirst = NULL;             \ | 
|---|
| 36 | (head).lpQHLast = &(head).lpQHFirst; \ | 
|---|
| 37 | } while(0) | 
|---|
| 38 |  | 
|---|
| 39 | /* Front of the queue */ | 
|---|
| 40 | #define DPQ_FIRST( head ) ( (head).lpQHFirst ) | 
|---|
| 41 |  | 
|---|
| 42 | /* Check if the queue has any elements */ | 
|---|
| 43 | #define DPQ_IS_EMPTY( head ) ( DPQ_FIRST(head) == NULL ) | 
|---|
| 44 |  | 
|---|
| 45 | /* Next entry -- FIXME: Convert everything over to this macro ... */ | 
|---|
| 46 | #define DPQ_NEXT( elem ) (elem).lpQNext | 
|---|
| 47 |  | 
|---|
| 48 | #define DPQ_IS_ENDOFLIST( elem ) \ | 
|---|
| 49 | ( DPQ_NEXT(elem) == NULL ) | 
|---|
| 50 |  | 
|---|
| 51 | /* Insert element at end of queue */ | 
|---|
| 52 | #define DPQ_INSERT_IN_TAIL(head, elm, field)     \ | 
|---|
| 53 | do {                                             \ | 
|---|
| 54 | (elm)->field.lpQNext = NULL;             \ | 
|---|
| 55 | (elm)->field.lpQPrev = (head).lpQHLast;  \ | 
|---|
| 56 | *(head).lpQHLast = (elm);                \ | 
|---|
| 57 | (head).lpQHLast = &(elm)->field.lpQNext; \ | 
|---|
| 58 | } while(0) | 
|---|
| 59 |  | 
|---|
| 60 | /* Remove element from the queue */ | 
|---|
| 61 | #define DPQ_REMOVE(head, elm, field)                    \ | 
|---|
| 62 | do {                                                    \ | 
|---|
| 63 | if (((elm)->field.lpQNext) != NULL)             \ | 
|---|
| 64 | (elm)->field.lpQNext->field.lpQPrev =   \ | 
|---|
| 65 | (elm)->field.lpQPrev;               \ | 
|---|
| 66 | else                                            \ | 
|---|
| 67 | (head).lpQHLast = (elm)->field.lpQPrev; \ | 
|---|
| 68 | *(elm)->field.lpQPrev = (elm)->field.lpQNext;   \ | 
|---|
| 69 | } while(0) | 
|---|
| 70 |  | 
|---|
| 71 | /* head - pointer to DPQ_HEAD struct | 
|---|
| 72 | * elm  - how to find the next element | 
|---|
| 73 | * field - to be concatenated to rc to compare with fieldToCompare | 
|---|
| 74 | * fieldToCompare - The value that we're comparing against | 
|---|
| 75 | * fieldCompareOperator - The logical operator to compare field and | 
|---|
| 76 | *                        fieldToCompare. | 
|---|
| 77 | * rc - Variable to put the return code. Same type as (head).lpQHFirst | 
|---|
| 78 | */ | 
|---|
| 79 | #define DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\ | 
|---|
| 80 | do {                                                           \ | 
|---|
| 81 | (rc) = DPQ_FIRST(head); /* NULL head? */                     \ | 
|---|
| 82 | \ | 
|---|
| 83 | while( rc )                                                  \ | 
|---|
| 84 | {                                                            \ | 
|---|
| 85 | /* What we're searching for? */                          \ | 
|---|
| 86 | if( (rc)->field fieldCompareOperator (fieldToCompare) )  \ | 
|---|
| 87 | {                                                        \ | 
|---|
| 88 | break; /* rc == correct element */                     \ | 
|---|
| 89 | }                                                        \ | 
|---|
| 90 | \ | 
|---|
| 91 | /* End of list check */                                  \ | 
|---|
| 92 | if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst )   \ | 
|---|
| 93 | {                                                        \ | 
|---|
| 94 | rc = NULL;                                             \ | 
|---|
| 95 | break;                                                 \ | 
|---|
| 96 | }                                                        \ | 
|---|
| 97 | }                                                            \ | 
|---|
| 98 | } while(0) | 
|---|
| 99 |  | 
|---|
| 100 | /* head - pointer to DPQ_HEAD struct | 
|---|
| 101 | * elm  - how to find the next element | 
|---|
| 102 | * field - to be concatenated to rc to compare with fieldToCompare | 
|---|
| 103 | * fieldToCompare - The value that we're comparing against | 
|---|
| 104 | * compare_cb - Callback to invoke to determine if comparision should continue. | 
|---|
| 105 | *              Callback must be defined with DPQ_DECL_COMPARECB. | 
|---|
| 106 | * rc - Variable to put the return code. Same type as (head).lpQHFirst | 
|---|
| 107 | */ | 
|---|
| 108 | #define DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\ | 
|---|
| 109 | do {                                                           \ | 
|---|
| 110 | (rc) = DPQ_FIRST(head); /* NULL head? */                     \ | 
|---|
| 111 | \ | 
|---|
| 112 | while( rc )                                                  \ | 
|---|
| 113 | {                                                            \ | 
|---|
| 114 | /* What we're searching for? */                          \ | 
|---|
| 115 | if( compare_cb( &((rc)->field), &(fieldToCompare) ) )    \ | 
|---|
| 116 | {                                                        \ | 
|---|
| 117 | break; /* no more */                                   \ | 
|---|
| 118 | }                                                        \ | 
|---|
| 119 | \ | 
|---|
| 120 | /* End of list check */                                  \ | 
|---|
| 121 | if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst )   \ | 
|---|
| 122 | {                                                        \ | 
|---|
| 123 | rc = NULL;                                             \ | 
|---|
| 124 | break;                                                 \ | 
|---|
| 125 | }                                                        \ | 
|---|
| 126 | }                                                            \ | 
|---|
| 127 | } while(0) | 
|---|
| 128 |  | 
|---|
| 129 | /* How to define the method to be passed to DPQ_DELETEQ */ | 
|---|
| 130 | #define DPQ_DECL_COMPARECB( name, type ) BOOL name( const type* elem1, const type* elem2 ) | 
|---|
| 131 |  | 
|---|
| 132 |  | 
|---|
| 133 | /* head - pointer to DPQ_HEAD struct | 
|---|
| 134 | * elm  - how to find the next element | 
|---|
| 135 | * field - to be concatenated to rc to compare with fieldToEqual | 
|---|
| 136 | * fieldToCompare - The value that we're comparing against | 
|---|
| 137 | * fieldCompareOperator - The logical operator to compare field and | 
|---|
| 138 | *                        fieldToCompare. | 
|---|
| 139 | * rc - Variable to put the return code. Same type as (head).lpQHFirst | 
|---|
| 140 | */ | 
|---|
| 141 | #define DPQ_REMOVE_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\ | 
|---|
| 142 | do {                                                           \ | 
|---|
| 143 | DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\ | 
|---|
| 144 | \ | 
|---|
| 145 | /* Was the element found? */                                 \ | 
|---|
| 146 | if( rc )                                                     \ | 
|---|
| 147 | {                                                            \ | 
|---|
| 148 | DPQ_REMOVE( head, rc, elm );                               \ | 
|---|
| 149 | }                                                            \ | 
|---|
| 150 | } while(0) | 
|---|
| 151 |  | 
|---|
| 152 | /* head - pointer to DPQ_HEAD struct | 
|---|
| 153 | * elm  - how to find the next element | 
|---|
| 154 | * field - to be concatenated to rc to compare with fieldToCompare | 
|---|
| 155 | * fieldToCompare - The value that we're comparing against | 
|---|
| 156 | * compare_cb - Callback to invoke to determine if comparision should continue. | 
|---|
| 157 | *              Callback must be defined with DPQ_DECL_COMPARECB. | 
|---|
| 158 | * rc - Variable to put the return code. Same type as (head).lpQHFirst | 
|---|
| 159 | */ | 
|---|
| 160 | #define DPQ_REMOVE_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\ | 
|---|
| 161 | do {                                                           \ | 
|---|
| 162 | DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc );\ | 
|---|
| 163 | \ | 
|---|
| 164 | /* Was the element found? */                                 \ | 
|---|
| 165 | if( rc )                                                     \ | 
|---|
| 166 | {                                                            \ | 
|---|
| 167 | DPQ_REMOVE( head, rc, elm );                               \ | 
|---|
| 168 | }                                                            \ | 
|---|
| 169 | } while(0) | 
|---|
| 170 |  | 
|---|
| 171 |  | 
|---|
| 172 | /* Delete the entire queue | 
|---|
| 173 | * head - pointer to the head of the queue | 
|---|
| 174 | * field - field to access the next elements of the queue | 
|---|
| 175 | * type - type of the pointer to the element element | 
|---|
| 176 | * df - a delete function to be called. Declared with DPQ_DECL_DELETECB. | 
|---|
| 177 | */ | 
|---|
| 178 | #define DPQ_DELETEQ( head, field, type, df )     \ | 
|---|
| 179 | do                                               \ | 
|---|
| 180 | {                                                \ | 
|---|
| 181 | while( !DPQ_IS_EMPTY(head) )                   \ | 
|---|
| 182 | {                                              \ | 
|---|
| 183 | type holder = DPQ_FIRST(head);               \ | 
|---|
| 184 | DPQ_REMOVE( head, holder, field );           \ | 
|---|
| 185 | df( holder );                                \ | 
|---|
| 186 | }                                              \ | 
|---|
| 187 | } while(0) | 
|---|
| 188 |  | 
|---|
| 189 | /* How to define the method to be passed to DPQ_DELETEQ */ | 
|---|
| 190 | #define DPQ_DECL_DELETECB( name, type ) void name( type elem ) | 
|---|
| 191 |  | 
|---|
| 192 | /* Prototype of a method which just performs a HeapFree on the elem */ | 
|---|
| 193 | DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID ); | 
|---|
| 194 |  | 
|---|
| 195 | #endif /* __WINE_DPLAYX_QUEUE_H */ | 
|---|