Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Queue_impl
comparison PrivateQueue.c @ 18:7c9e00ff1bf4
fixed queue enlarging function
| author | Merten Sach <msach@mailbox.tu-berlin.de> |
|---|---|
| date | Wed, 22 Jun 2011 18:49:17 +0200 |
| parents | 1e93e5dbeda1 |
| children | 677afc259a58 |
comparison
equal
deleted
inserted
replaced
| 11:9e5d29d7b4f4 | 12:4f82930118bf |
|---|---|
| 37 } | 37 } |
| 38 | 38 |
| 39 | 39 |
| 40 void | 40 void |
| 41 enlargePrivQ( PrivQueueStruc *Q ) | 41 enlargePrivQ( PrivQueueStruc *Q ) |
| 42 { int oldSize, newSize; | 42 { size_t oldSize, newSize; |
| 43 void **oldStartOfData; | 43 void **oldStartOfData; |
| 44 | 44 |
| 45 oldSize = Q->endOfData - Q->startOfData; | 45 oldSize = Q->endOfData - Q->startOfData + 1; |
| 46 newSize = 2 * oldSize; | 46 newSize = 2 * oldSize; |
| 47 oldStartOfData = Q->startOfData; | 47 oldStartOfData = Q->startOfData; |
| 48 Q->startOfData = VMS__malloc( newSize * sizeof(void *) ); | 48 Q->startOfData = VMS__malloc( newSize * sizeof(void*)); |
| 49 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); | 49 //copy second half |
| 50 size_t secondHalfSize = Q->endOfData - Q->extractPos + 1; | |
| 51 memcpy(Q->startOfData,Q->extractPos, secondHalfSize * sizeof(void*)); | |
| 52 //copy first half | |
| 53 memcpy(Q->startOfData + secondHalfSize, oldStartOfData, | |
| 54 (oldSize-secondHalfSize) * sizeof(void*)); | |
| 50 VMS__free(oldStartOfData); | 55 VMS__free(oldStartOfData); |
| 51 | 56 |
| 52 Q->extractPos = &(Q->startOfData[0]); //side by side == empty | 57 Q->extractPos = Q->startOfData; |
| 53 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be | 58 Q->insertPos = Q->startOfData + oldSize - 1; |
| 54 Q->endOfData = &(Q->startOfData[newSize - 1]); | 59 Q->endOfData = &(Q->startOfData[newSize - 1]); |
| 55 } | 60 } |
| 56 | 61 |
| 57 | 62 |
| 58 /*Returns NULL when queue is empty | 63 /*Returns NULL when queue is empty |
| 104 /*Expands the queue size automatically when it's full | 109 /*Expands the queue size automatically when it's full |
| 105 */ | 110 */ |
| 106 void | 111 void |
| 107 writePrivQ( void * in, PrivQueueStruc* Q ) | 112 writePrivQ( void * in, PrivQueueStruc* Q ) |
| 108 { | 113 { |
| 109 void **startOfData = Q->startOfData; | 114 while(1){ |
| 110 void **endOfData = Q->endOfData; | 115 void **startOfData = Q->startOfData; |
| 111 | 116 void **endOfData = Q->endOfData; |
| 112 void **insertPos = Q->insertPos; | 117 |
| 113 void **extractPos = Q->extractPos; | 118 void **insertPos = Q->insertPos; |
| 114 | 119 void **extractPos = Q->extractPos; |
| 115 tryAgain: | 120 |
| 116 //Full? (insert is just below extract when full) | 121 //Full? (insert is just below extract when full) |
| 117 if( extractPos - insertPos != 1 && | 122 if( extractPos - insertPos != 1 && |
| 118 !(insertPos == endOfData && extractPos == startOfData)) | 123 !(insertPos == endOfData && extractPos == startOfData)) |
| 119 { *(Q->insertPos) = in; //insert before move | 124 { *(Q->insertPos) = in; //insert before move |
| 120 if( insertPos == endOfData ) //write new pos exactly once, correctly | 125 if( insertPos == endOfData ) //write new pos exactly once, correctly |
| 121 { Q->insertPos = startOfData; | 126 { Q->insertPos = startOfData; |
| 122 } | 127 } |
| 123 else | 128 else |
| 124 { Q->insertPos++; | 129 { Q->insertPos++; |
| 125 } | 130 } |
| 126 return; | 131 return; |
| 127 } | 132 } |
| 128 //Q is full | 133 //Q is full |
| 129 enlargePrivQ( Q ); | 134 enlargePrivQ( Q ); |
| 130 goto tryAgain; | 135 } |
| 131 } | 136 } |
| 132 | 137 |
| 133 | 138 |
| 134 /*Returns false when the queue was full. | 139 /*Returns false when the queue was full. |
| 135 * have option of calling make_larger_PrivQ to make more room, then try again | 140 * have option of calling make_larger_PrivQ to make more room, then try again |
| 162 * Expands the queue size automatically when it's full. | 167 * Expands the queue size automatically when it's full. |
| 163 */ | 168 */ |
| 164 void | 169 void |
| 165 pushPrivQ( void * in, PrivQueueStruc* Q ) | 170 pushPrivQ( void * in, PrivQueueStruc* Q ) |
| 166 { | 171 { |
| 167 void **startOfData = Q->startOfData; | 172 while(1){ |
| 168 void **endOfData = Q->endOfData; | 173 void **startOfData = Q->startOfData; |
| 169 | 174 void **endOfData = Q->endOfData; |
| 170 void **insertPos = Q->insertPos; | 175 |
| 171 void **extractPos = Q->extractPos; | 176 void **insertPos = Q->insertPos; |
| 172 | 177 void **extractPos = Q->extractPos; |
| 173 tryAgain: | 178 |
| 174 //Full? (insert is just below extract when full) | 179 //Full? (insert is just below extract when full) |
| 175 if( extractPos - insertPos != 1 && | 180 if( extractPos - insertPos != 1 && |
| 176 !(insertPos == endOfData && extractPos == startOfData)) | 181 !(insertPos == endOfData && extractPos == startOfData)) |
| 177 { //insert -- but go backwards, inserting at read position then | 182 { //insert -- but go backwards, inserting at read position then |
| 178 // move read pos backwards | 183 // move read pos backwards |
| 179 *(Q->extractPos) = in; | 184 *(Q->extractPos) = in; |
| 180 if( extractPos == startOfData ) //write new pos exactly once, correctly | 185 if( extractPos == startOfData ) //write new pos exactly once, correctly |
| 181 { Q->extractPos = endOfData; //can't overrun then fix it 'cause | 186 { Q->extractPos = endOfData; //can't overrun then fix it 'cause |
| 182 } // other thread might read bad pos | 187 } // other thread might read bad pos |
| 183 else | 188 else |
| 184 { Q->extractPos--; | 189 { Q->extractPos--; |
| 185 } | 190 } |
| 186 return; | 191 return; |
| 187 } | 192 } |
| 188 //Q is full | 193 //Q is full |
| 189 enlargePrivQ( Q ); | 194 enlargePrivQ( Q ); |
| 190 goto tryAgain; | 195 } |
| 191 } | 196 } |
| 192 | 197 |
| 193 void | 198 void |
| 194 freePrivQ( PrivQueueStruc *Q ) | 199 freePrivQ( PrivQueueStruc *Q ) |
| 195 { | 200 { |
