annotate PrivateQueue.c @ 0:85af604dee9b

initial add
author Me
date Sat, 22 May 2010 19:51:09 -0700
parents
children f4d50d8a1a38
rev   line source
Me@0 1 /*
Me@0 2 * Copyright 2009 OpenSourceCodeStewardshipFoundation.org
Me@0 3 * Licensed under GNU General Public License version 2
Me@0 4 *
Me@0 5 * NOTE: this version of SRSW correct as of April 25, 2010
Me@0 6 *
Me@0 7 * Author: seanhalle@yahoo.com
Me@0 8 */
Me@0 9
Me@0 10
Me@0 11 #include <stdio.h>
Me@0 12 #include <string.h>
Me@0 13 #include <errno.h>
Me@0 14 #include <stdlib.h>
Me@0 15
Me@0 16 #include "PrivateQueue.h"
Me@0 17
Me@0 18
Me@0 19
Me@0 20 //===========================================================================
Me@0 21
Me@0 22 /*This kind of queue is private to a single core at a time -- has no
Me@0 23 * synchronizations
Me@0 24 */
Me@0 25
Me@0 26 PrivQueueStruc* makePrivQ()
Me@0 27 {
Me@0 28 PrivQueueStruc* retQ;
Me@0 29 retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) );
Me@0 30
Me@0 31 retQ->startOfData = malloc( 1024 * sizeof(void *) );
Me@0 32
Me@0 33 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
Me@0 34 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
Me@0 35 retQ->endOfData = &(retQ->startOfData[1023]);
Me@0 36
Me@0 37 return retQ;
Me@0 38 }
Me@0 39
Me@0 40 PrivQueueStruc* make_larger_PrivQ( 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@0 46 Q->startOfData = malloc( newSize * sizeof(void *) );
Me@0 47 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *));
Me@0 48 free(oldStartOfData);
Me@0 49
Me@0 50 Q->extractPos = &(Q->startOfData[0]); //side by side == empty
Me@0 51 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be
Me@0 52 Q->endOfData = &(Q->startOfData[newSize - 1]);
Me@0 53
Me@0 54 return Q;
Me@0 55 }
Me@0 56
Me@0 57
Me@0 58 /*Returns NULL when queue is empty
Me@0 59 */
Me@0 60 void* readPrivQ( PrivQueueStruc* Q )
Me@0 61 { void *out = 0;
Me@0 62 int startOfData = Q->startOfData;
Me@0 63 int endOfData = Q->endOfData;
Me@0 64
Me@0 65 volatile int insertPos = Q->insertPos;
Me@0 66 volatile int extractPos = Q->extractPos;
Me@0 67
Me@0 68 //if not empty -- extract just below insert when empty
Me@0 69 if( insertPos - extractPos != 1 &&
Me@0 70 !(extractPos == endOfData && insertPos == startOfData))
Me@0 71 { //move before read
Me@0 72 if( extractPos == endOfData ) //write new pos exactly once, correctly
Me@0 73 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
Me@0 74 } // other thread might read bad pos
Me@0 75 else
Me@0 76 { Q->extractPos++;
Me@0 77 }
Me@0 78 out = *(Q->extractPos);
Me@0 79 return out;
Me@0 80 }
Me@0 81 //Q is empty
Me@0 82 return NULL;
Me@0 83 }
Me@0 84
Me@0 85 /*Returns false when the queue was full.
Me@0 86 * have option of calling make_larger_PrivQ to make more room, then try again
Me@0 87 */
Me@0 88 bool8 writePrivQ( void * in, PrivQueueStruc* Q )
Me@0 89 {
Me@0 90 int startOfData = Q->startOfData;
Me@0 91 int endOfData = Q->endOfData;
Me@0 92
Me@0 93 volatile int insertPos = Q->insertPos;
Me@0 94 volatile int extractPos = Q->extractPos;
Me@0 95
Me@0 96 if( extractPos - insertPos != 1 &&
Me@0 97 !(insertPos == endOfData && extractPos == startOfData))
Me@0 98 { *(insertPos) = in; //insert before move
Me@0 99 if( insertPos == endOfData ) //write new pos exactly once, correctly
Me@0 100 { Q->insertPos = startOfData;
Me@0 101 }
Me@0 102 else
Me@0 103 { Q->insertPos++;
Me@0 104 }
Me@0 105 return TRUE;
Me@0 106 }
Me@0 107 //Q is full
Me@0 108 return FALSE;
Me@0 109 }
Me@0 110