Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Queue_impl
comparison PrivateQueue.c @ 34:c5d2f2a94133
updated to fixed versions from MC_shared brch, then removed VMS_ from malloc
| author | Some Random Person <seanhalle@yahoo.com> |
|---|---|
| date | Wed, 14 Mar 2012 23:02:28 -0700 |
| parents | 1ed562d601d9 |
| children | d6da470bbd38 |
comparison
equal
deleted
inserted
replaced
| 13:d6e6de89698a | 20:11e7c3bb6780 |
|---|---|
| 24 */ | 24 */ |
| 25 | 25 |
| 26 PrivQueueStruc* makePrivQ() | 26 PrivQueueStruc* makePrivQ() |
| 27 { | 27 { |
| 28 PrivQueueStruc* retQ; | 28 PrivQueueStruc* retQ; |
| 29 //This malloc is not safe to use inside VMS-language! | |
| 29 retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) ); | 30 retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) ); |
| 30 | 31 |
| 32 //This malloc is not safe to use inside VMS-language! | |
| 31 retQ->startOfData = malloc( 1024 * sizeof(void *) ); | 33 retQ->startOfData = malloc( 1024 * sizeof(void *) ); |
| 32 memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); | 34 memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); |
| 33 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty | 35 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty |
| 34 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be | 36 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be |
| 35 retQ->endOfData = &(retQ->startOfData[1023]); | 37 retQ->endOfData = &(retQ->startOfData[1023]); |
| 38 } | 40 } |
| 39 | 41 |
| 40 | 42 |
| 41 void | 43 void |
| 42 enlargePrivQ( PrivQueueStruc *Q ) | 44 enlargePrivQ( PrivQueueStruc *Q ) |
| 43 { int oldSize, newSize; | 45 { int32 oldSize, newSize; |
| 44 void **oldStartOfData; | 46 int8 *insertPos, *extractPos; |
| 45 | 47 int8 *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData; |
| 46 oldSize = Q->endOfData - Q->startOfData; | 48 int8 *insertOffsetBytes, *extractOffsetBytes; |
| 47 newSize = 2 * oldSize; | 49 |
| 48 oldStartOfData = Q->startOfData; | 50 oldStartOfData = (int8 *)Q->startOfData; |
| 49 Q->startOfData = malloc( newSize * sizeof(void *) ); | 51 oldEndOfData = (int8 *)Q->endOfData; |
| 50 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); | 52 insertPos = (int8 *)Q->insertPos; |
| 51 free(oldStartOfData); | 53 extractPos = (int8 *)Q->extractPos; |
| 52 | 54 |
| 53 Q->extractPos = &(Q->startOfData[0]); //side by side == empty | 55 //TODO: verify these get number of bytes correct |
| 54 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be | 56 insertOffsetBytes = insertPos - oldStartOfData; |
| 55 Q->endOfData = &(Q->startOfData[newSize - 1]); | 57 extractOffsetBytes = extractPos - oldStartOfData); |
| 58 | |
| 59 oldSize = endOfData - startOfData + 1; //in bytes | |
| 60 newSize = 2 * oldSize; | |
| 61 | |
| 62 //This malloc is not safe to use inside VMS-language! | |
| 63 Q->startOfData = (void **)malloc( newSize ); | |
| 64 newStartOfData = (int8 *)Q->startOfData; | |
| 65 newEndOfData = newStartOfData + newSize; //all calcs in Bytes | |
| 66 Q->endOfData = (void **)newEndOfData; | |
| 67 | |
| 68 //TODO: test all of this, for both cases | |
| 69 | |
| 70 //Moving the data and pointers to the new array is | |
| 71 //a little trickier than at first it seems.. the top part | |
| 72 // of old queue must be moved to the top part of new queue, while | |
| 73 // bottom part of old to bottom part of new, then the new insert | |
| 74 // and extract positions calculated by offset from top and bottom | |
| 75 //UNLESS the one case where old extract was at bottom and insert | |
| 76 // was at top. | |
| 77 //TODO: check that this is correct! | |
| 78 if( extractPos == startOfData && insertPos == endOfData ) | |
| 79 { | |
| 80 memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes | |
| 81 Q->extractPos = Q->startOfData; //start of valid data | |
| 82 Q->insertPos = Q->startOfData + oldSize - 1; //end of valid data | |
| 83 } | |
| 84 else //have to copy two parts separately, then calc positions | |
| 85 { //TODO: check end-addr, sizes, and new positions carefully | |
| 86 | |
| 87 //copy top part, starting at extract up until end of data, | |
| 88 // into top of new array | |
| 89 topPartSize = oldEndOfData - extractPos + 1; //+1 includes extractPos | |
| 90 copyStartAddr = newEndOfData - topPartSize + 1;//+1 cancels other | |
| 91 memcpy( copyStartAddr, Q->extractPos, topPartSize ); | |
| 92 Q->extractPos = (void **)copyStartAddr; //extract just-copied data | |
| 93 | |
| 94 //copy bottom part, from old start up to old insert, | |
| 95 // into bottom of new array | |
| 96 bottPartSize = oldSize - topPartSize - 1; //-1 for empty insertPos | |
| 97 memcpy( newStartOfData, oldStartOfData, bottPartSize ); | |
| 98 Q->insertPos = (void **)(newStartOfData + bottPartSize); | |
| 99 } | |
| 100 //This free is not safe to use inside VMS-language! | |
| 101 free(oldStartOfData); | |
| 56 } | 102 } |
| 57 | 103 |
| 58 | 104 |
| 59 /*Returns NULL when queue is empty | 105 /*Returns NULL when queue is empty |
| 60 */ | 106 */ |
| 137 return TRUE; | 183 return TRUE; |
| 138 } | 184 } |
| 139 //Q is full | 185 //Q is full |
| 140 return FALSE; | 186 return FALSE; |
| 141 } | 187 } |
| 188 | |
| 189 int32 | |
| 190 numInPrivQ( PrivQueueStruc *Q ) | |
| 191 { int32 size, numIn; | |
| 192 | |
| 193 if( Q->insertPos < Q->extractPos ) | |
| 194 { //insert has wrapped around so numIn is: | |
| 195 // insertPos + size - extractPos -- Consider, is empty when | |
| 196 // extractPos = endOfData and insert = start -- correctly get zero | |
| 197 size = Q->endOfData - Q->startOfData + 1; //sz of 10 is 0..9 | |
| 198 numIn = Q->insertPos - Q->extractPos + size - 1; //-1 bec insrt empty | |
| 199 } | |
| 200 else | |
| 201 { | |
| 202 numIn = Q->insertPos - Q->extractPos -1;//-1 bec insertPos empty | |
| 203 } | |
| 204 return numIn; | |
| 205 } | |
| 206 | |
| 207 | |
| 208 /*Treats queue as a stack -- no matter contents, if read done right after | |
| 209 * a push, then the pushed item is what comes out. | |
| 210 * Expands the queue size automatically when it's full. | |
| 211 */ | |
| 212 void | |
| 213 pushPrivQ( void * in, PrivQueueStruc* Q ) | |
| 214 { | |
| 215 while(1){ | |
| 216 void **startOfData = Q->startOfData; | |
| 217 void **endOfData = Q->endOfData; | |
| 218 | |
| 219 void **insertPos = Q->insertPos; | |
| 220 void **extractPos = Q->extractPos; | |
| 221 | |
| 222 //Full? (insert is just below extract when full) | |
| 223 if( extractPos - insertPos != 1 && | |
| 224 !(insertPos == endOfData && extractPos == startOfData)) | |
| 225 { //insert -- but go backwards, inserting at read position then | |
| 226 // move read pos backwards | |
| 227 *(Q->extractPos) = in; | |
| 228 if( extractPos == startOfData ) //write new pos exactly once, correctly | |
| 229 { Q->extractPos = endOfData; //can't overrun then fix it 'cause | |
| 230 } // other thread might read bad pos | |
| 231 else | |
| 232 { Q->extractPos--; | |
| 233 } | |
| 234 return; | |
| 235 } | |
| 236 //Q is full | |
| 237 enlargePrivQ( Q ); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 | |
| 242 void | |
| 243 freePrivQ( PrivQueueStruc *Q ) | |
| 244 { | |
| 245 //This free is not safe to use inside VMS-language! | |
| 246 free( Q->startOfData ); | |
| 247 free( Q ); | |
| 248 } |
