Me@0: /* Me@8: * Copyright 2009 OpenSourceStewardshipFoundation.org Me@0: * Licensed under GNU General Public License version 2 Me@0: * Me@0: * Author: seanhalle@yahoo.com Me@0: */ Me@0: Me@0: Me@0: #include Me@0: #include Me@0: #include Me@0: #include Me@0: Me@0: #include "PrivateQueue.h" Me@0: Me@0: Me@0: Me@0: //=========================================================================== Me@0: Me@0: /*This kind of queue is private to a single core at a time -- has no Me@0: * synchronizations Me@0: */ Me@0: Me@0: PrivQueueStruc* makePrivQ() Me@0: { Me@0: PrivQueueStruc* retQ; Me@9: retQ = (PrivQueueStruc *) VMS__malloc( sizeof( PrivQueueStruc ) ); Me@0: Me@9: retQ->startOfData = VMS__malloc( 1024 * sizeof(void *) ); Me@14: memset( retQ->startOfData, 0, 1024 ); Me@14: Me@0: retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty Me@0: retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be Me@0: retQ->endOfData = &(retQ->startOfData[1023]); Me@0: Me@0: return retQ; Me@0: } Me@0: Me@2: Me@2: void Me@2: enlargePrivQ( PrivQueueStruc *Q ) Me@0: { int oldSize, newSize; Me@0: void **oldStartOfData; Me@0: Me@0: oldSize = Q->endOfData - Q->startOfData; Me@0: newSize = 2 * oldSize; Me@6: oldStartOfData = Q->startOfData; Me@9: Q->startOfData = VMS__malloc( newSize * sizeof(void *) ); Me@0: memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); Me@9: VMS__free(oldStartOfData); Me@0: Me@0: Q->extractPos = &(Q->startOfData[0]); //side by side == empty Me@0: Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be Me@0: Q->endOfData = &(Q->startOfData[newSize - 1]); Me@0: } Me@0: Me@0: Me@0: /*Returns NULL when queue is empty Me@0: */ Me@0: void* readPrivQ( PrivQueueStruc* Q ) Me@0: { void *out = 0; Me@2: void **startOfData = Q->startOfData; Me@2: void **endOfData = Q->endOfData; Me@0: Me@2: void **insertPos = Q->insertPos; Me@2: void **extractPos = Q->extractPos; Me@0: Me@6: //if not empty -- (extract is just below insert when empty) Me@0: if( insertPos - extractPos != 1 && Me@0: !(extractPos == endOfData && insertPos == startOfData)) Me@0: { //move before read Me@0: if( extractPos == endOfData ) //write new pos exactly once, correctly Me@0: { Q->extractPos = startOfData; //can't overrun then fix it 'cause Me@0: } // other thread might read bad pos Me@0: else Me@0: { Q->extractPos++; Me@0: } Me@0: out = *(Q->extractPos); Me@0: return out; Me@0: } Me@0: //Q is empty Me@0: return NULL; Me@0: } Me@0: Me@11: int32 Me@11: numInPrivQ( PrivQueueStruc *Q ) Me@11: { int32 size, numIn; Me@11: Me@11: if( Q->insertPos < Q->extractPos ) Me@11: { //insert has wrapped around so numIn is: Me@11: // insertPos + size - extractPos -- Consider, is empty when Me@11: // extractPos = endOfData and insert = start -- correctly get zero Me@11: size = Q->endOfData - Q->startOfData; Me@11: numIn = Q->insertPos + size - Q->extractPos; Me@11: } Me@11: else Me@11: { Me@11: numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side Me@11: } Me@11: return numIn; Me@11: } Me@11: Me@2: Me@2: /*Expands the queue size automatically when it's full Me@2: */ Me@2: void Me@6: writePrivQ( void * in, PrivQueueStruc* Q ) Me@2: { Me@2: void **startOfData = Q->startOfData; Me@2: void **endOfData = Q->endOfData; Me@2: Me@2: void **insertPos = Q->insertPos; Me@2: void **extractPos = Q->extractPos; Me@2: Me@2: tryAgain: Me@6: //Full? (insert is just below extract when full) Me@2: if( extractPos - insertPos != 1 && Me@2: !(insertPos == endOfData && extractPos == startOfData)) Me@2: { *(Q->insertPos) = in; //insert before move Me@2: if( insertPos == endOfData ) //write new pos exactly once, correctly Me@2: { Q->insertPos = startOfData; Me@2: } Me@2: else Me@2: { Q->insertPos++; Me@2: } Me@2: return; Me@2: } Me@2: //Q is full Me@2: enlargePrivQ( Q ); Me@2: goto tryAgain; Me@2: } Me@2: Me@2: Me@0: /*Returns false when the queue was full. Me@0: * have option of calling make_larger_PrivQ to make more room, then try again Me@0: */ Me@6: int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ) Me@0: { Me@2: void **startOfData = Q->startOfData; Me@2: void **endOfData = Q->endOfData; Me@2: Me@2: void **insertPos = Q->insertPos; Me@2: void **extractPos = Q->extractPos; Me@0: Me@0: if( extractPos - insertPos != 1 && Me@0: !(insertPos == endOfData && extractPos == startOfData)) Me@2: { *(Q->insertPos) = in; //insert before move Me@0: if( insertPos == endOfData ) //write new pos exactly once, correctly Me@0: { Q->insertPos = startOfData; Me@0: } Me@0: else Me@0: { Q->insertPos++; Me@0: } Me@0: return TRUE; Me@0: } Me@0: //Q is full Me@0: return FALSE; Me@0: } Me@9: Me@9: void Me@9: freePrivQ( PrivQueueStruc *Q ) Me@9: { Me@9: VMS__free( Q->startOfData ); Me@9: VMS__free( Q ); Me@9: }