Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Queue_impl
changeset 32:a74011c0b78b MC_shared
fixed expansion of queue, and added numInPrivQ and freePrivQ
| author | Some Random Person <seanhalle@yahoo.com> |
|---|---|
| date | Wed, 14 Mar 2012 22:48:50 -0700 |
| parents | 555cc068a79a |
| children | 501206566d16 |
| files | PrivateQueue.c PrivateQueue.h |
| diffstat | 2 files changed, 125 insertions(+), 17 deletions(-) [+] |
line diff
1.1 --- a/PrivateQueue.c Tue Mar 13 18:31:06 2012 -0700 1.2 +++ b/PrivateQueue.c Wed Mar 14 22:48:50 2012 -0700 1.3 @@ -26,8 +26,10 @@ 1.4 PrivQueueStruc* makePrivQ() 1.5 { 1.6 PrivQueueStruc* retQ; 1.7 - retQ = (PrivQueueStruc *) VMS_WL__malloc( sizeof( PrivQueueStruc ) ); 1.8 + //This malloc is not safe to use in wrapper lib nor app code! 1.9 + retQ = (PrivQueueStruc *) VMS_int__malloc( sizeof( PrivQueueStruc ) ); 1.10 1.11 + //This malloc is not safe to use in wrapper lib nor app code! 1.12 retQ->startOfData = VMS_WL__malloc( 1024 * sizeof(void *) ); 1.13 memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); 1.14 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty 1.15 @@ -40,19 +42,63 @@ 1.16 1.17 void 1.18 enlargePrivQ( PrivQueueStruc *Q ) 1.19 - { int oldSize, newSize; 1.20 - void **oldStartOfData; 1.21 + { int32 oldSize, newSize; 1.22 + int8 *insertPos, *extractPos; 1.23 + int8 *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData; 1.24 + int8 *insertOffsetBytes, *extractOffsetBytes; 1.25 1.26 - oldSize = Q->endOfData - Q->startOfData; 1.27 - newSize = 2 * oldSize; 1.28 - oldStartOfData = Q->startOfData; 1.29 - Q->startOfData = VMS_WL__malloc( newSize * sizeof(void *) ); 1.30 - memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); 1.31 - VMS_int__free(oldStartOfData); 1.32 + oldStartOfData = (int8 *)Q->startOfData; 1.33 + oldEndOfData = (int8 *)Q->endOfData; 1.34 + insertPos = (int8 *)Q->insertPos; 1.35 + extractPos = (int8 *)Q->extractPos; 1.36 1.37 - Q->extractPos = &(Q->startOfData[0]); //side by side == empty 1.38 - Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be 1.39 - Q->endOfData = &(Q->startOfData[newSize - 1]); 1.40 + //TODO: verify these get number of bytes correct 1.41 + insertOffsetBytes = insertPos - oldStartOfData; 1.42 + extractOffsetBytes = extractPos - oldStartOfData); 1.43 + 1.44 + oldSize = endOfData - startOfData + 1; //in bytes 1.45 + newSize = 2 * oldSize; 1.46 + 1.47 + //This malloc is not safe to use in wrapper lib nor app code! 1.48 + Q->startOfData = (void **)VMS_int__malloc( newSize ); 1.49 + newStartOfData = (int8 *)Q->startOfData; 1.50 + newEndOfData = newStartOfData + newSize; //all calcs in Bytes 1.51 + Q->endOfData = (void **)newEndOfData; 1.52 + 1.53 + //TODO: test all of this, for both cases 1.54 + 1.55 + //Moving the data and pointers to the new array is 1.56 + //a little trickier than at first it seems.. the top part 1.57 + // of old queue must be moved to the top part of new queue, while 1.58 + // bottom part of old to bottom part of new, then the new insert 1.59 + // and extract positions calculated by offset from top and bottom 1.60 + //UNLESS the one case where old extract was at bottom and insert 1.61 + // was at top. 1.62 + //TODO: check that this is correct! 1.63 + if( extractPos == startOfData && insertPos == endOfData ) 1.64 + { 1.65 + memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes 1.66 + Q->extractPos = Q->startOfData; //start of valid data 1.67 + Q->insertPos = Q->startOfData + oldSize - 1; //end of valid data 1.68 + } 1.69 + else //have to copy two parts separately, then calc positions 1.70 + { //TODO: check end-addr, sizes, and new positions carefully 1.71 + 1.72 + //copy top part, starting at extract up until end of data, 1.73 + // into top of new array 1.74 + topPartSize = oldEndOfData - extractPos + 1; //+1 includes extractPos 1.75 + copyStartAddr = newEndOfData - topPartSize + 1;//+1 cancels other 1.76 + memcpy( copyStartAddr, Q->extractPos, topPartSize ); 1.77 + Q->extractPos = (void **)copyStartAddr; //extract just-copied data 1.78 + 1.79 + //copy bottom part, from old start up to old insert, 1.80 + // into bottom of new array 1.81 + bottPartSize = oldSize - topPartSize - 1; //-1 for empty insertPos 1.82 + memcpy( newStartOfData, oldStartOfData, bottPartSize ); 1.83 + Q->insertPos = (void **)(newStartOfData + bottPartSize); 1.84 + } 1.85 + //This free is not safe to use in wrapper lib nor app code! 1.86 + VMS_int__free(oldStartOfData); 1.87 } 1.88 1.89 1.90 @@ -140,6 +186,25 @@ 1.91 return FALSE; 1.92 } 1.93 1.94 +int32 1.95 +numInPrivQ( PrivQueueStruc *Q ) 1.96 + { int32 size, numIn; 1.97 + 1.98 + if( Q->insertPos < Q->extractPos ) 1.99 + { //insert has wrapped around so numIn is: 1.100 + // insertPos + size - extractPos -- Consider, is empty when 1.101 + // extractPos = endOfData and insert = start -- correctly get zero 1.102 + size = Q->endOfData - Q->startOfData; 1.103 + numIn = Q->insertPos + size - Q->extractPos; 1.104 + } 1.105 + else 1.106 + { 1.107 + numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side 1.108 + } 1.109 + return numIn; 1.110 + } 1.111 + 1.112 + 1.113 int 1.114 numInPrivQ( PrivQueueStruc *Q ) 1.115 { 1.116 @@ -155,3 +220,45 @@ 1.117 return size - numEmpty; 1.118 } 1.119 } 1.120 + 1.121 +/*Treats queue as a stack -- no matter contents, if read done right after 1.122 + * a push, then the pushed item is what comes out. 1.123 + * Expands the queue size automatically when it's full. 1.124 + */ 1.125 +void 1.126 +pushPrivQ( void * in, PrivQueueStruc* Q ) 1.127 + { 1.128 + while(1){ 1.129 + void **startOfData = Q->startOfData; 1.130 + void **endOfData = Q->endOfData; 1.131 + 1.132 + void **insertPos = Q->insertPos; 1.133 + void **extractPos = Q->extractPos; 1.134 + 1.135 + //Full? (insert is just below extract when full) 1.136 + if( extractPos - insertPos != 1 && 1.137 + !(insertPos == endOfData && extractPos == startOfData)) 1.138 + { //insert -- but go backwards, inserting at read position then 1.139 + // move read pos backwards 1.140 + *(Q->extractPos) = in; 1.141 + if( extractPos == startOfData ) //write new pos exactly once, correctly 1.142 + { Q->extractPos = endOfData; //can't overrun then fix it 'cause 1.143 + } // other thread might read bad pos 1.144 + else 1.145 + { Q->extractPos--; 1.146 + } 1.147 + return; 1.148 + } 1.149 + //Q is full 1.150 + enlargePrivQ( Q ); 1.151 + } 1.152 + } 1.153 + 1.154 + 1.155 + void 1.156 + freePrivQ( PrivQueueStruc *Q ) 1.157 + { 1.158 + //This free is not safe to use in wrapper lib nor app code! 1.159 + VMS_int__free( Q->startOfData ); 1.160 + VMS_int__free( Q ); 1.161 + } 1.162 \ No newline at end of file
2.1 --- a/PrivateQueue.h Tue Mar 13 18:31:06 2012 -0700 2.2 +++ b/PrivateQueue.h Wed Mar 14 22:48:50 2012 -0700 2.3 @@ -32,12 +32,13 @@ 2.4 typedef void (*DynArrayFnPtr) ( void * ); //fn has to cast void * 2.5 2.6 PrivQueueStruc* makePrivQ ( ); 2.7 -void* readPrivQ ( PrivQueueStruc *Q ); 2.8 +void* readPrivQ ( PrivQueueStruc *Q ); //ret NULL if empty 2.9 void writePrivQ( void *in, PrivQueueStruc *Q ); 2.10 -int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ); //return 2.11 -int numInPrivQ( PrivQueueStruc *Q ); 2.12 - // false when full 2.13 - 2.14 + //return false when full 2.15 +bool32 writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ); 2.16 +int32 numInPrivQ( PrivQueueStruc *Q ); 2.17 +void pushPrivQ( void * in, PrivQueueStruc* Q ); 2.18 +void freePrivQ( PrivQueueStruc *Q ); 2.19 2.20 #endif /* _PRIVATE_QUEUE_H */ 2.21
