annotate PrivateQueue.c @ 12:3134d8a1e8e3

added pushPrivQ -- treats Q as stack, pushed elem is first out
author SeanHalle
date Thu, 11 Nov 2010 04:19:01 -0800
parents 3562716ebdbd
children 1ab93714b9c1
rev   line source
Me@0 1 /*
Me@8 2 * Copyright 2009 OpenSourceStewardshipFoundation.org
Me@0 3 * Licensed under GNU General Public License version 2
Me@0 4 *
Me@0 5 * Author: seanhalle@yahoo.com
Me@0 6 */
Me@0 7
Me@0 8
Me@0 9 #include <stdio.h>
Me@0 10 #include <string.h>
Me@0 11 #include <errno.h>
Me@0 12 #include <stdlib.h>
Me@0 13
Me@0 14 #include "PrivateQueue.h"
Me@0 15
Me@0 16
Me@0 17
Me@0 18 //===========================================================================
Me@0 19
Me@0 20 /*This kind of queue is private to a single core at a time -- has no
Me@0 21 * synchronizations
Me@0 22 */
Me@0 23
Me@0 24 PrivQueueStruc* makePrivQ()
Me@0 25 {
Me@0 26 PrivQueueStruc* retQ;
Me@9 27 retQ = (PrivQueueStruc *) VMS__malloc( sizeof( PrivQueueStruc ) );
Me@0 28
Me@9 29 retQ->startOfData = VMS__malloc( 1024 * sizeof(void *) );
Me@0 30
Me@0 31 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
Me@0 32 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
Me@0 33 retQ->endOfData = &(retQ->startOfData[1023]);
Me@0 34
Me@0 35 return retQ;
Me@0 36 }
Me@0 37
Me@2 38
Me@2 39 void
Me@2 40 enlargePrivQ( PrivQueueStruc *Q )
Me@0 41 { int oldSize, newSize;
Me@0 42 void **oldStartOfData;
Me@0 43
Me@0 44 oldSize = Q->endOfData - Q->startOfData;
Me@0 45 newSize = 2 * oldSize;
Me@6 46 oldStartOfData = Q->startOfData;
Me@9 47 Q->startOfData = VMS__malloc( newSize * sizeof(void *) );
Me@0 48 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *));
Me@9 49 VMS__free(oldStartOfData);
Me@0 50
Me@0 51 Q->extractPos = &(Q->startOfData[0]); //side by side == empty
Me@0 52 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be
Me@0 53 Q->endOfData = &(Q->startOfData[newSize - 1]);
Me@0 54 }
Me@0 55
Me@0 56
Me@0 57 /*Returns NULL when queue is empty
Me@0 58 */
Me@0 59 void* readPrivQ( PrivQueueStruc* Q )
Me@0 60 { void *out = 0;
Me@2 61 void **startOfData = Q->startOfData;
Me@2 62 void **endOfData = Q->endOfData;
Me@0 63
Me@2 64 void **insertPos = Q->insertPos;
Me@2 65 void **extractPos = Q->extractPos;
Me@0 66
Me@6 67 //if not empty -- (extract is just below insert when empty)
Me@0 68 if( insertPos - extractPos != 1 &&
Me@0 69 !(extractPos == endOfData && insertPos == startOfData))
Me@0 70 { //move before read
Me@0 71 if( extractPos == endOfData ) //write new pos exactly once, correctly
Me@0 72 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
Me@0 73 } // other thread might read bad pos
Me@0 74 else
Me@0 75 { Q->extractPos++;
Me@0 76 }
Me@0 77 out = *(Q->extractPos);
Me@0 78 return out;
Me@0 79 }
Me@0 80 //Q is empty
Me@0 81 return NULL;
Me@0 82 }
Me@0 83
Me@11 84 int32
Me@11 85 numInPrivQ( PrivQueueStruc *Q )
Me@11 86 { int32 size, numIn;
Me@11 87
Me@11 88 if( Q->insertPos < Q->extractPos )
Me@11 89 { //insert has wrapped around so numIn is:
Me@11 90 // insertPos + size - extractPos -- Consider, is empty when
Me@11 91 // extractPos = endOfData and insert = start -- correctly get zero
Me@11 92 size = Q->endOfData - Q->startOfData;
Me@11 93 numIn = Q->insertPos + size - Q->extractPos;
Me@11 94 }
Me@11 95 else
Me@11 96 {
Me@11 97 numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side
Me@11 98 }
Me@11 99 return numIn;
Me@11 100 }
Me@11 101
Me@2 102
Me@2 103 /*Expands the queue size automatically when it's full
Me@2 104 */
Me@2 105 void
Me@6 106 writePrivQ( void * in, PrivQueueStruc* Q )
Me@2 107 {
Me@2 108 void **startOfData = Q->startOfData;
Me@2 109 void **endOfData = Q->endOfData;
Me@2 110
Me@2 111 void **insertPos = Q->insertPos;
Me@2 112 void **extractPos = Q->extractPos;
Me@2 113
Me@2 114 tryAgain:
Me@6 115 //Full? (insert is just below extract when full)
Me@2 116 if( extractPos - insertPos != 1 &&
Me@2 117 !(insertPos == endOfData && extractPos == startOfData))
Me@2 118 { *(Q->insertPos) = in; //insert before move
Me@2 119 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@2 120 { Q->insertPos = startOfData;
Me@2 121 }
Me@2 122 else
Me@2 123 { Q->insertPos++;
Me@2 124 }
Me@2 125 return;
Me@2 126 }
Me@2 127 //Q is full
Me@2 128 enlargePrivQ( Q );
Me@2 129 goto tryAgain;
Me@2 130 }
Me@2 131
Me@2 132
Me@0 133 /*Returns false when the queue was full.
Me@0 134 * have option of calling make_larger_PrivQ to make more room, then try again
Me@0 135 */
Me@6 136 int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
Me@0 137 {
Me@2 138 void **startOfData = Q->startOfData;
Me@2 139 void **endOfData = Q->endOfData;
Me@2 140
Me@2 141 void **insertPos = Q->insertPos;
Me@2 142 void **extractPos = Q->extractPos;
Me@0 143
Me@0 144 if( extractPos - insertPos != 1 &&
Me@0 145 !(insertPos == endOfData && extractPos == startOfData))
Me@2 146 { *(Q->insertPos) = in; //insert before move
Me@0 147 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@0 148 { Q->insertPos = startOfData;
Me@0 149 }
Me@0 150 else
Me@0 151 { Q->insertPos++;
Me@0 152 }
Me@0 153 return TRUE;
Me@0 154 }
Me@0 155 //Q is full
Me@0 156 return FALSE;
Me@0 157 }
Me@9 158
SeanHalle@12 159 /*Treats queue as a stack -- no matter contents, if read done right after
SeanHalle@12 160 * a push, then the pushed item is what comes out.
SeanHalle@12 161 * Expands the queue size automatically when it's full.
SeanHalle@12 162 */
SeanHalle@12 163 void
SeanHalle@12 164 pushPrivQ( void * in, PrivQueueStruc* Q )
SeanHalle@12 165 {
SeanHalle@12 166 void **startOfData = Q->startOfData;
SeanHalle@12 167 void **endOfData = Q->endOfData;
SeanHalle@12 168
SeanHalle@12 169 void **insertPos = Q->insertPos;
SeanHalle@12 170 void **extractPos = Q->extractPos;
SeanHalle@12 171
SeanHalle@12 172 tryAgain:
SeanHalle@12 173 //Full? (insert is just below extract when full)
SeanHalle@12 174 if( extractPos - insertPos != 1 &&
SeanHalle@12 175 !(insertPos == endOfData && extractPos == startOfData))
SeanHalle@12 176 { //insert -- but go backwards, inserting at read position then
SeanHalle@12 177 // move read pos backwards
SeanHalle@12 178 *(Q->extractPos) = in;
SeanHalle@12 179 if( extractPos == startOfData ) //write new pos exactly once, correctly
SeanHalle@12 180 { Q->extractPos = endOfData; //can't overrun then fix it 'cause
SeanHalle@12 181 } // other thread might read bad pos
SeanHalle@12 182 else
SeanHalle@12 183 { Q->extractPos--;
SeanHalle@12 184 }
SeanHalle@12 185 return;
SeanHalle@12 186 }
SeanHalle@12 187 //Q is full
SeanHalle@12 188 enlargePrivQ( Q );
SeanHalle@12 189 goto tryAgain;
SeanHalle@12 190 }
SeanHalle@12 191
Me@9 192 void
Me@9 193 freePrivQ( PrivQueueStruc *Q )
Me@9 194 {
Me@9 195 VMS__free( Q->startOfData );
Me@9 196 VMS__free( Q );
Me@9 197 }