annotate PrivateQueue.c @ 27:bd38feb38c80

Added numInPrivQ
author Some Random Person <seanhalle@yahoo.com>
date Sun, 04 Mar 2012 14:25:24 -0800
parents 59781a4c9cf1
children a74011c0b78b
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@27 29 retQ = (PrivQueueStruc *) VMS_WL__malloc( sizeof( PrivQueueStruc ) );
Me@19 30
seanhalle@27 31 retQ->startOfData = VMS_WL__malloc( 1024 * sizeof(void *) );
Me@19 32 memset( retQ->startOfData, 0, 1024 * sizeof(void *) );
Me@19 33 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
Me@19 34 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
Me@19 35 retQ->endOfData = &(retQ->startOfData[1023]);
Me@19 36
Me@19 37 return retQ;
Me@19 38 }
Me@19 39
Me@19 40
Me@19 41 void
Me@19 42 enlargePrivQ( PrivQueueStruc *Q )
Me@19 43 { int oldSize, newSize;
Me@19 44 void **oldStartOfData;
Me@19 45
Me@19 46 oldSize = Q->endOfData - Q->startOfData;
Me@19 47 newSize = 2 * oldSize;
Me@19 48 oldStartOfData = Q->startOfData;
seanhalle@27 49 Q->startOfData = VMS_WL__malloc( newSize * sizeof(void *) );
Me@19 50 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *));
Me@22 51 VMS_int__free(oldStartOfData);
Me@19 52
Me@19 53 Q->extractPos = &(Q->startOfData[0]); //side by side == empty
Me@19 54 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be
Me@19 55 Q->endOfData = &(Q->startOfData[newSize - 1]);
Me@19 56 }
Me@19 57
Me@19 58
Me@19 59 /*Returns NULL when queue is empty
Me@19 60 */
Me@19 61 void* readPrivQ( PrivQueueStruc* Q )
Me@19 62 { void *out = 0;
Me@19 63 void **startOfData = Q->startOfData;
Me@19 64 void **endOfData = Q->endOfData;
Me@19 65
Me@19 66 void **insertPos = Q->insertPos;
Me@19 67 void **extractPos = Q->extractPos;
Me@19 68
Me@19 69 //if not empty -- (extract is just below insert when empty)
Me@19 70 if( insertPos - extractPos != 1 &&
Me@19 71 !(extractPos == endOfData && insertPos == startOfData))
Me@19 72 { //move before read
Me@19 73 if( extractPos == endOfData ) //write new pos exactly once, correctly
Me@19 74 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
Me@19 75 } // other thread might read bad pos
Me@19 76 else
Me@19 77 { Q->extractPos++;
Me@19 78 }
Me@19 79 out = *(Q->extractPos);
Me@19 80 return out;
Me@19 81 }
Me@19 82 //Q is empty
Me@19 83 return NULL;
Me@19 84 }
Me@19 85
Me@19 86
Me@19 87 /*Expands the queue size automatically when it's full
Me@19 88 */
Me@19 89 void
Me@19 90 writePrivQ( void * in, PrivQueueStruc* Q )
Me@19 91 {
Me@19 92 void **startOfData = Q->startOfData;
Me@19 93 void **endOfData = Q->endOfData;
Me@19 94
Me@19 95 void **insertPos = Q->insertPos;
Me@19 96 void **extractPos = Q->extractPos;
Me@19 97
Me@19 98 tryAgain:
Me@19 99 //Full? (insert is just below extract when full)
Me@19 100 if( extractPos - insertPos != 1 &&
Me@19 101 !(insertPos == endOfData && extractPos == startOfData))
Me@19 102 { *(Q->insertPos) = in; //insert before move
Me@19 103 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@19 104 { Q->insertPos = startOfData;
Me@19 105 }
Me@19 106 else
Me@19 107 { Q->insertPos++;
Me@19 108 }
Me@19 109 return;
Me@19 110 }
Me@19 111 //Q is full
Me@19 112 enlargePrivQ( Q );
Me@19 113 goto tryAgain;
Me@19 114 }
Me@19 115
Me@19 116
Me@19 117 /*Returns false when the queue was full.
Me@19 118 * have option of calling make_larger_PrivQ to make more room, then try again
Me@19 119 */
Me@19 120 int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
Me@19 121 {
Me@19 122 void **startOfData = Q->startOfData;
Me@19 123 void **endOfData = Q->endOfData;
Me@19 124
Me@19 125 void **insertPos = Q->insertPos;
Me@19 126 void **extractPos = Q->extractPos;
Me@19 127
Me@19 128 if( extractPos - insertPos != 1 &&
Me@19 129 !(insertPos == endOfData && extractPos == startOfData))
Me@19 130 { *(Q->insertPos) = in; //insert before move
Me@19 131 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@19 132 { Q->insertPos = startOfData;
Me@19 133 }
Me@19 134 else
Me@19 135 { Q->insertPos++;
Me@19 136 }
Me@19 137 return TRUE;
Me@19 138 }
Me@19 139 //Q is full
Me@19 140 return FALSE;
Me@19 141 }
seanhalle@27 142
seanhalle@27 143 int
seanhalle@27 144 numInPrivQ( PrivQueueStruc *Q )
seanhalle@27 145 {
seanhalle@27 146 void **insertPos = Q->insertPos;
seanhalle@27 147 void **extractPos = Q->extractPos;
seanhalle@27 148
seanhalle@27 149 int numInQ;
seanhalle@27 150
seanhalle@27 151 if( (numInQ = insertPos - extractPos) >= 0 ) return numInQ;
seanhalle@27 152 else
seanhalle@27 153 { int size = Q->endOfData - Q->startOfData;
seanhalle@27 154 int numEmpty = extractPos - insertPos; //not efficient, but easier to read
seanhalle@27 155 return size - numEmpty;
seanhalle@27 156 }
seanhalle@27 157 }