annotate PrivateQueue.c @ 35:3f5e365143fd

New states for sub-repos, almost works, just bug in shutdown to fix still
author Some Random Person <seanhalle@yahoo.com>
date Wed, 14 Mar 2012 23:22:00 -0700
parents 501206566d16
children b9cb01d8ce56
rev   line source
Me@19 1 /*
Me@19 2 * Copyright 2009 OpenSourceStewardshipFoundation.org
Me@19 3 * Licensed under GNU General Public License version 2
Me@19 4 *
Me@19 5 * NOTE: this version of SRSW correct as of April 25, 2010
Me@19 6 *
Me@19 7 * Author: seanhalle@yahoo.com
Me@19 8 */
Me@19 9
Me@19 10
Me@19 11 #include <stdio.h>
Me@19 12 #include <string.h>
Me@19 13 #include <errno.h>
Me@19 14 #include <stdlib.h>
Me@19 15
Me@19 16 #include "PrivateQueue.h"
Me@19 17
Me@19 18
Me@19 19
Me@19 20 //===========================================================================
Me@19 21
Me@19 22 /*This kind of queue is private to a single core at a time -- has no
Me@19 23 * synchronizations
Me@19 24 */
Me@19 25
Me@19 26 PrivQueueStruc* makePrivQ()
Me@19 27 {
Me@19 28 PrivQueueStruc* retQ;
seanhalle@32 29 //This malloc is not safe to use in wrapper lib nor app code!
seanhalle@32 30 retQ = (PrivQueueStruc *) VMS_int__malloc( sizeof( PrivQueueStruc ) );
Me@19 31
seanhalle@32 32 //This malloc is not safe to use in wrapper lib nor app code!
seanhalle@27 33 retQ->startOfData = VMS_WL__malloc( 1024 * sizeof(void *) );
Me@19 34 memset( retQ->startOfData, 0, 1024 * sizeof(void *) );
Me@19 35 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
Me@19 36 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
Me@19 37 retQ->endOfData = &(retQ->startOfData[1023]);
Me@19 38
Me@19 39 return retQ;
Me@19 40 }
Me@19 41
Me@19 42
Me@19 43 void
Me@19 44 enlargePrivQ( PrivQueueStruc *Q )
seanhalle@35 45 { int32 oldSize, newSize, topPartSize, bottPartSize;
seanhalle@32 46 int8 *insertPos, *extractPos;
seanhalle@32 47 int8 *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData;
seanhalle@35 48 int32 insertOffsetBytes, extractOffsetBytes;
seanhalle@35 49 int8 *copyStartAddr;
Me@19 50
seanhalle@32 51 oldStartOfData = (int8 *)Q->startOfData;
seanhalle@32 52 oldEndOfData = (int8 *)Q->endOfData;
seanhalle@32 53 insertPos = (int8 *)Q->insertPos;
seanhalle@32 54 extractPos = (int8 *)Q->extractPos;
Me@19 55
seanhalle@32 56 //TODO: verify these get number of bytes correct
seanhalle@35 57 insertOffsetBytes = (int32)(insertPos - oldStartOfData);
seanhalle@35 58 extractOffsetBytes = (int32)(extractPos - oldStartOfData);
seanhalle@32 59
seanhalle@35 60 oldSize = oldEndOfData - oldStartOfData + 1; //in bytes
seanhalle@32 61 newSize = 2 * oldSize;
seanhalle@32 62
seanhalle@32 63 //This malloc is not safe to use in wrapper lib nor app code!
seanhalle@32 64 Q->startOfData = (void **)VMS_int__malloc( newSize );
seanhalle@32 65 newStartOfData = (int8 *)Q->startOfData;
seanhalle@32 66 newEndOfData = newStartOfData + newSize; //all calcs in Bytes
seanhalle@32 67 Q->endOfData = (void **)newEndOfData;
seanhalle@32 68
seanhalle@32 69 //TODO: test all of this, for both cases
seanhalle@32 70
seanhalle@32 71 //Moving the data and pointers to the new array is
seanhalle@32 72 //a little trickier than at first it seems.. the top part
seanhalle@32 73 // of old queue must be moved to the top part of new queue, while
seanhalle@32 74 // bottom part of old to bottom part of new, then the new insert
seanhalle@32 75 // and extract positions calculated by offset from top and bottom
seanhalle@32 76 //UNLESS the one case where old extract was at bottom and insert
seanhalle@32 77 // was at top.
seanhalle@32 78 //TODO: check that this is correct!
seanhalle@35 79 if( extractPos == oldStartOfData && insertPos == oldEndOfData )
seanhalle@32 80 {
seanhalle@32 81 memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes
seanhalle@32 82 Q->extractPos = Q->startOfData; //start of valid data
seanhalle@32 83 Q->insertPos = Q->startOfData + oldSize - 1; //end of valid data
seanhalle@32 84 }
seanhalle@32 85 else //have to copy two parts separately, then calc positions
seanhalle@32 86 { //TODO: check end-addr, sizes, and new positions carefully
seanhalle@35 87
seanhalle@32 88 //copy top part, starting at extract up until end of data,
seanhalle@35 89 // into top of new array
seanhalle@32 90 topPartSize = oldEndOfData - extractPos + 1; //+1 includes extractPos
seanhalle@35 91 copyStartAddr = newEndOfData - topPartSize + 1;//+1 cancels other
seanhalle@32 92 memcpy( copyStartAddr, Q->extractPos, topPartSize );
seanhalle@35 93 Q->extractPos = (void **)copyStartAddr; //extract just-copied data
seanhalle@35 94
seanhalle@32 95 //copy bottom part, from old start up to old insert,
seanhalle@35 96 // into bottom of new array
seanhalle@32 97 bottPartSize = oldSize - topPartSize - 1; //-1 for empty insertPos
seanhalle@32 98 memcpy( newStartOfData, oldStartOfData, bottPartSize );
seanhalle@32 99 Q->insertPos = (void **)(newStartOfData + bottPartSize);
seanhalle@32 100 }
seanhalle@32 101 //This free is not safe to use in wrapper lib nor app code!
seanhalle@32 102 VMS_int__free(oldStartOfData);
Me@19 103 }
Me@19 104
Me@19 105
Me@19 106 /*Returns NULL when queue is empty
Me@19 107 */
Me@19 108 void* readPrivQ( PrivQueueStruc* Q )
Me@19 109 { void *out = 0;
Me@19 110 void **startOfData = Q->startOfData;
Me@19 111 void **endOfData = Q->endOfData;
Me@19 112
Me@19 113 void **insertPos = Q->insertPos;
Me@19 114 void **extractPos = Q->extractPos;
Me@19 115
Me@19 116 //if not empty -- (extract is just below insert when empty)
Me@19 117 if( insertPos - extractPos != 1 &&
Me@19 118 !(extractPos == endOfData && insertPos == startOfData))
Me@19 119 { //move before read
Me@19 120 if( extractPos == endOfData ) //write new pos exactly once, correctly
Me@19 121 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
Me@19 122 } // other thread might read bad pos
Me@19 123 else
Me@19 124 { Q->extractPos++;
Me@19 125 }
Me@19 126 out = *(Q->extractPos);
Me@19 127 return out;
Me@19 128 }
Me@19 129 //Q is empty
Me@19 130 return NULL;
Me@19 131 }
Me@19 132
Me@19 133
Me@19 134 /*Expands the queue size automatically when it's full
Me@19 135 */
Me@19 136 void
Me@19 137 writePrivQ( void * in, PrivQueueStruc* Q )
Me@19 138 {
Me@19 139 void **startOfData = Q->startOfData;
Me@19 140 void **endOfData = Q->endOfData;
Me@19 141
Me@19 142 void **insertPos = Q->insertPos;
Me@19 143 void **extractPos = Q->extractPos;
Me@19 144
Me@19 145 tryAgain:
Me@19 146 //Full? (insert is just below extract when full)
Me@19 147 if( extractPos - insertPos != 1 &&
Me@19 148 !(insertPos == endOfData && extractPos == startOfData))
Me@19 149 { *(Q->insertPos) = in; //insert before move
Me@19 150 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@19 151 { Q->insertPos = startOfData;
Me@19 152 }
Me@19 153 else
Me@19 154 { Q->insertPos++;
Me@19 155 }
Me@19 156 return;
Me@19 157 }
Me@19 158 //Q is full
Me@19 159 enlargePrivQ( Q );
Me@19 160 goto tryAgain;
Me@19 161 }
Me@19 162
Me@19 163
Me@19 164 /*Returns false when the queue was full.
Me@19 165 * have option of calling make_larger_PrivQ to make more room, then try again
Me@19 166 */
seanhalle@35 167 bool32
seanhalle@35 168 writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
Me@19 169 {
Me@19 170 void **startOfData = Q->startOfData;
Me@19 171 void **endOfData = Q->endOfData;
Me@19 172
Me@19 173 void **insertPos = Q->insertPos;
Me@19 174 void **extractPos = Q->extractPos;
Me@19 175
Me@19 176 if( extractPos - insertPos != 1 &&
Me@19 177 !(insertPos == endOfData && extractPos == startOfData))
Me@19 178 { *(Q->insertPos) = in; //insert before move
Me@19 179 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@19 180 { Q->insertPos = startOfData;
Me@19 181 }
Me@19 182 else
Me@19 183 { Q->insertPos++;
Me@19 184 }
Me@19 185 return TRUE;
Me@19 186 }
Me@19 187 //Q is full
Me@19 188 return FALSE;
Me@19 189 }
seanhalle@27 190
seanhalle@32 191 int32
seanhalle@32 192 numInPrivQ( PrivQueueStruc *Q )
seanhalle@32 193 { int32 size, numIn;
seanhalle@32 194
seanhalle@32 195 if( Q->insertPos < Q->extractPos )
seanhalle@32 196 { //insert has wrapped around so numIn is:
seanhalle@32 197 // insertPos + size - extractPos -- Consider, is empty when
seanhalle@32 198 // extractPos = endOfData and insert = start -- correctly get zero
seanhalle@33 199 size = Q->endOfData - Q->startOfData + 1; //sz of 10 is 0..9
seanhalle@33 200 numIn = Q->insertPos - Q->extractPos + size - 1; //-1 bec insrt empty
seanhalle@32 201 }
seanhalle@32 202 else
seanhalle@32 203 {
seanhalle@33 204 numIn = Q->insertPos - Q->extractPos -1;//-1 bec insertPos empty
seanhalle@32 205 }
seanhalle@32 206 return numIn;
seanhalle@32 207 }
seanhalle@32 208
seanhalle@32 209
seanhalle@32 210 /*Treats queue as a stack -- no matter contents, if read done right after
seanhalle@32 211 * a push, then the pushed item is what comes out.
seanhalle@32 212 * Expands the queue size automatically when it's full.
seanhalle@32 213 */
seanhalle@32 214 void
seanhalle@32 215 pushPrivQ( void * in, PrivQueueStruc* Q )
seanhalle@32 216 {
seanhalle@32 217 while(1){
seanhalle@32 218 void **startOfData = Q->startOfData;
seanhalle@32 219 void **endOfData = Q->endOfData;
seanhalle@32 220
seanhalle@32 221 void **insertPos = Q->insertPos;
seanhalle@32 222 void **extractPos = Q->extractPos;
seanhalle@32 223
seanhalle@32 224 //Full? (insert is just below extract when full)
seanhalle@32 225 if( extractPos - insertPos != 1 &&
seanhalle@32 226 !(insertPos == endOfData && extractPos == startOfData))
seanhalle@32 227 { //insert -- but go backwards, inserting at read position then
seanhalle@32 228 // move read pos backwards
seanhalle@32 229 *(Q->extractPos) = in;
seanhalle@32 230 if( extractPos == startOfData ) //write new pos exactly once, correctly
seanhalle@32 231 { Q->extractPos = endOfData; //can't overrun then fix it 'cause
seanhalle@32 232 } // other thread might read bad pos
seanhalle@32 233 else
seanhalle@32 234 { Q->extractPos--;
seanhalle@32 235 }
seanhalle@32 236 return;
seanhalle@32 237 }
seanhalle@32 238 //Q is full
seanhalle@32 239 enlargePrivQ( Q );
seanhalle@32 240 }
seanhalle@32 241 }
seanhalle@32 242
seanhalle@32 243
seanhalle@32 244 void
seanhalle@32 245 freePrivQ( PrivQueueStruc *Q )
seanhalle@32 246 {
seanhalle@32 247 //This free is not safe to use in wrapper lib nor app code!
seanhalle@32 248 VMS_int__free( Q->startOfData );
seanhalle@32 249 VMS_int__free( Q );
seanhalle@32 250 }