Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Queue_impl
diff PrivateQueue.c @ 41:8fcbe46de60a
bugfixes - peek and enlarge now working properly
| author | Nina Engelhardt <nengel@mailbox.tu-berlin.de> |
|---|---|
| date | Wed, 19 Dec 2012 15:38:08 +0100 |
| parents | b9cb01d8ce56 |
| children | c54f7e0a9d11 |
line diff
1.1 --- a/PrivateQueue.c Tue Sep 11 04:19:51 2012 -0700 1.2 +++ b/PrivateQueue.c Wed Dec 19 15:38:08 2012 +0100 1.3 @@ -8,10 +8,9 @@ 1.4 */ 1.5 1.6 1.7 +#include <string.h> 1.8 +#include <stdlib.h> 1.9 #include <stdio.h> 1.10 -#include <string.h> 1.11 -#include <errno.h> 1.12 -#include <stdlib.h> 1.13 1.14 #include "PrivateQueue.h" 1.15 1.16 @@ -36,38 +35,54 @@ 1.17 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be 1.18 retQ->endOfData = &(retQ->startOfData[1023]); 1.19 1.20 + #ifdef DEBUG_PRIVATE_Q 1.21 + retQ->numReads = 0; 1.22 + retQ->numWrites =0; 1.23 + #endif 1.24 + 1.25 return retQ; 1.26 } 1.27 1.28 1.29 void 1.30 enlargePrivQ( PrivQueueStruc *Q ) 1.31 - { int32 oldSize, newSize, topPartSize, bottPartSize; 1.32 - int8 *insertPos, *extractPos; 1.33 - int8 *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData; 1.34 - int32 insertOffsetBytes, extractOffsetBytes; 1.35 - int8 *copyStartAddr; 1.36 + { size_t oldSize, newSize, topPartSize, bottPartSize; 1.37 + char *insertPos, *extractPos; 1.38 + char *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData; 1.39 + size_t insertOffsetBytes, extractOffsetBytes; 1.40 + char* copyStartAddr; 1.41 1.42 - oldStartOfData = (int8 *)Q->startOfData; 1.43 - oldEndOfData = (int8 *)Q->endOfData; 1.44 - insertPos = (int8 *)Q->insertPos; 1.45 - extractPos = (int8 *)Q->extractPos; 1.46 + #ifdef DEBUG_PRIVATE_Q 1.47 + printf("Enlarging queue Q = %p\nnumReads = %d; numWrites = %d\n",Q,Q->numReads,Q->numWrites); 1.48 + #endif 1.49 + 1.50 + oldStartOfData = (char*)Q->startOfData; 1.51 + oldEndOfData = (char*)(Q->endOfData + 1); 1.52 + insertPos = (char*)Q->insertPos; 1.53 + extractPos = (char*)Q->extractPos; 1.54 1.55 //TODO: verify these get number of bytes correct 1.56 - insertOffsetBytes = (int32)(insertPos - oldStartOfData); 1.57 - extractOffsetBytes = (int32)(extractPos - oldStartOfData); 1.58 + insertOffsetBytes = (insertPos - oldStartOfData); 1.59 + extractOffsetBytes = (extractPos - oldStartOfData); 1.60 1.61 - oldSize = oldEndOfData - oldStartOfData + 1; //in bytes 1.62 + oldSize = oldEndOfData - oldStartOfData; //in bytes 1.63 newSize = 2 * oldSize; 1.64 1.65 + #ifdef DEBUG_PRIVATE_Q 1.66 + printf("Old size = %d, new size = %d\n",(int)oldSize,(int)newSize); 1.67 + #endif 1.68 + 1.69 //This malloc is not safe to use in wrapper lib nor app code! 1.70 - Q->startOfData = (void **)VMS_int__malloc( newSize ); 1.71 - newStartOfData = (int8 *)Q->startOfData; 1.72 + newStartOfData = (char *) VMS_int__malloc( newSize ); 1.73 + if(newStartOfData == NULL){ 1.74 + perror("malloc"); exit(1); 1.75 + } 1.76 newEndOfData = newStartOfData + newSize; //all calcs in Bytes 1.77 - Q->endOfData = (void **)newEndOfData; 1.78 + 1.79 + //TODO: test all of this, for both cases 1.80 + Q->startOfData = newStartOfData; 1.81 + Q->endOfData = ((void **)newEndOfData) - 1; 1.82 1.83 - //TODO: test all of this, for both cases 1.84 - 1.85 //Moving the data and pointers to the new array is 1.86 //a little trickier than at first it seems.. the top part 1.87 // of old queue must be moved to the top part of new queue, while 1.88 @@ -76,25 +91,25 @@ 1.89 //UNLESS the one case where old extract was at bottom and insert 1.90 // was at top. 1.91 //TODO: check that this is correct! 1.92 - if( extractPos == oldStartOfData && insertPos == oldEndOfData ) 1.93 + if( extractPos == oldStartOfData ) 1.94 { 1.95 memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes 1.96 Q->extractPos = Q->startOfData; //start of valid data 1.97 - Q->insertPos = Q->startOfData + oldSize - 1; //end of valid data 1.98 + Q->insertPos = (void**)(newStartOfData + insertOffsetBytes); //end of valid data 1.99 } 1.100 else //have to copy two parts separately, then calc positions 1.101 { //TODO: check end-addr, sizes, and new positions carefully 1.102 - 1.103 + 1.104 //copy top part, starting at extract up until end of data, 1.105 // into top of new array 1.106 - topPartSize = oldEndOfData - extractPos + 1; //+1 includes extractPos 1.107 - copyStartAddr = newEndOfData - topPartSize + 1;//+1 cancels other 1.108 - memcpy( copyStartAddr, Q->extractPos, topPartSize ); 1.109 + topPartSize = oldEndOfData - extractPos; 1.110 + copyStartAddr = newEndOfData - topPartSize; 1.111 + memcpy( copyStartAddr, extractPos, topPartSize ); 1.112 Q->extractPos = (void **)copyStartAddr; //extract just-copied data 1.113 1.114 //copy bottom part, from old start up to old insert, 1.115 // into bottom of new array 1.116 - bottPartSize = oldSize - topPartSize - 1; //-1 for empty insertPos 1.117 + bottPartSize = insertPos - oldStartOfData; //-1 for empty insertPos 1.118 memcpy( newStartOfData, oldStartOfData, bottPartSize ); 1.119 Q->insertPos = (void **)(newStartOfData + bottPartSize); 1.120 } 1.121 @@ -137,70 +152,72 @@ 1.122 if( insertPos - extractPos != 1 && 1.123 !(extractPos == endOfData && insertPos == startOfData)) 1.124 { 1.125 - out = *(Q->extractPos); 1.126 + out = *(Q->extractPos + 1); 1.127 return out; 1.128 } 1.129 //Q is empty 1.130 return NULL; 1.131 } 1.132 1.133 - 1.134 /*Returns NULL when queue is empty 1.135 */ 1.136 -void* readPrivQ( PrivQueueStruc* Q ) 1.137 - { void *out = 0; 1.138 - void **startOfData = Q->startOfData; 1.139 - void **endOfData = Q->endOfData; 1.140 +void* readPrivQ(PrivQueueStruc* Q) { 1.141 +#ifdef DEBUG_PRIVATE_Q 1.142 + Q->numReads++; 1.143 +#endif 1.144 + 1.145 + void *out = 0; 1.146 + void **startOfData = Q->startOfData; 1.147 + void **endOfData = Q->endOfData; 1.148 1.149 - void **insertPos = Q->insertPos; 1.150 - void **extractPos = Q->extractPos; 1.151 + void **insertPos = Q->insertPos; 1.152 + void **extractPos = Q->extractPos; 1.153 1.154 - //if not empty -- (extract is just below insert when empty) 1.155 - if( insertPos - extractPos != 1 && 1.156 - !(extractPos == endOfData && insertPos == startOfData)) 1.157 - { //move before read 1.158 - if( extractPos == endOfData ) //write new pos exactly once, correctly 1.159 - { Q->extractPos = startOfData; //can't overrun then fix it 'cause 1.160 - } // other thread might read bad pos 1.161 - else 1.162 - { Q->extractPos++; 1.163 - } 1.164 - out = *(Q->extractPos); 1.165 - return out; 1.166 + //if not empty -- (extract is just below insert when empty) 1.167 + if (insertPos - extractPos != 1 && 1.168 + !(extractPos == endOfData && insertPos == startOfData)) { //move before read 1.169 + if (extractPos == endOfData) //write new pos exactly once, correctly 1.170 + { 1.171 + Q->extractPos = startOfData; //can't overrun then fix it 'cause 1.172 + }// other thread might read bad pos 1.173 + else { 1.174 + Q->extractPos++; 1.175 + } 1.176 + out = *(Q->extractPos); 1.177 + return out; 1.178 } 1.179 - //Q is empty 1.180 - return NULL; 1.181 - } 1.182 - 1.183 - 1.184 + //Q is empty 1.185 + return NULL; 1.186 +} 1.187 /*Expands the queue size automatically when it's full 1.188 */ 1.189 void 1.190 -writePrivQ( void * in, PrivQueueStruc* Q ) 1.191 - { 1.192 - void **startOfData = Q->startOfData; 1.193 - void **endOfData = Q->endOfData; 1.194 - 1.195 - void **insertPos = Q->insertPos; 1.196 - void **extractPos = Q->extractPos; 1.197 +writePrivQ(void * in, PrivQueueStruc* Q) { 1.198 1.199 -tryAgain: 1.200 - //Full? (insert is just below extract when full) 1.201 - if( extractPos - insertPos != 1 && 1.202 - !(insertPos == endOfData && extractPos == startOfData)) 1.203 - { *(Q->insertPos) = in; //insert before move 1.204 - if( insertPos == endOfData ) //write new pos exactly once, correctly 1.205 - { Q->insertPos = startOfData; 1.206 - } 1.207 - else 1.208 - { Q->insertPos++; 1.209 - } 1.210 - return; 1.211 + #ifdef DEBUG_PRIVATE_Q 1.212 + Q->numWrites++; 1.213 + #endif 1.214 + 1.215 + //tryAgain: 1.216 + //Full? (insert is just below extract when full) 1.217 + if ((Q->extractPos - Q->insertPos) == 1 || 1.218 + (Q->insertPos == Q->endOfData && Q->extractPos == Q->startOfData)) { 1.219 + enlargePrivQ(Q); 1.220 } 1.221 - //Q is full 1.222 - enlargePrivQ( Q ); 1.223 - goto tryAgain; 1.224 - } 1.225 + 1.226 + *(Q->insertPos) = in; //insert before move 1.227 + if (Q->insertPos == Q->endOfData) //write new pos exactly once, correctly 1.228 + { 1.229 + Q->insertPos = Q->startOfData; 1.230 + } else { 1.231 + Q->insertPos++; 1.232 + } 1.233 + return; 1.234 + 1.235 + //Q is full 1.236 + 1.237 + //goto tryAgain; 1.238 +} 1.239 1.240 1.241 /*Returns false when the queue was full. 1.242 @@ -224,6 +241,9 @@ 1.243 else 1.244 { Q->insertPos++; 1.245 } 1.246 + #ifdef DEBUG_PRIVATE_Q 1.247 + Q->numWrites++; 1.248 + #endif 1.249 return TRUE; 1.250 } 1.251 //Q is full 1.252 @@ -256,6 +276,9 @@ 1.253 void 1.254 pushPrivQ( void * in, PrivQueueStruc* Q ) 1.255 { 1.256 + #ifdef DEBUG_PRIVATE_Q 1.257 + Q->numWrites++; 1.258 + #endif 1.259 while(1){ 1.260 void **startOfData = Q->startOfData; 1.261 void **endOfData = Q->endOfData;
