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;