view PrivateQueue.c @ 4:8abcca1590b8

Tested and working on full VMS test
author Me
date Wed, 30 Jun 2010 14:34:56 -0700
parents 85af604dee9b
children 174a7c2ca340
line source
1 /*
2 * Copyright 2009 OpenSourceCodeStewardshipFoundation.org
3 * Licensed under GNU General Public License version 2
4 *
5 * NOTE: this version of SRSW correct as of April 25, 2010
6 *
7 * Author: seanhalle@yahoo.com
8 */
11 #include <stdio.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <stdlib.h>
16 #include "PrivateQueue.h"
20 //===========================================================================
22 /*This kind of queue is private to a single core at a time -- has no
23 * synchronizations
24 */
26 PrivQueueStruc* makePrivQ()
27 {
28 PrivQueueStruc* retQ;
29 retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) );
31 retQ->startOfData = malloc( 1024 * sizeof(void *) );
33 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
34 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
35 retQ->endOfData = &(retQ->startOfData[1023]);
37 return retQ;
38 }
41 void
42 enlargePrivQ( PrivQueueStruc *Q )
43 { int oldSize, newSize;
44 void **oldStartOfData;
46 oldSize = Q->endOfData - Q->startOfData;
47 newSize = 2 * oldSize;
48 Q->startOfData = malloc( newSize * sizeof(void *) );
49 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *));
50 free(oldStartOfData);
52 Q->extractPos = &(Q->startOfData[0]); //side by side == empty
53 Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be
54 Q->endOfData = &(Q->startOfData[newSize - 1]);
55 }
58 /*Returns NULL when queue is empty
59 */
60 void* readPrivQ( PrivQueueStruc* Q )
61 { void *out = 0;
62 void **startOfData = Q->startOfData;
63 void **endOfData = Q->endOfData;
65 void **insertPos = Q->insertPos;
66 void **extractPos = Q->extractPos;
68 //if not empty -- extract just below insert when empty
69 if( insertPos - extractPos != 1 &&
70 !(extractPos == endOfData && insertPos == startOfData))
71 { //move before read
72 if( extractPos == endOfData ) //write new pos exactly once, correctly
73 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
74 } // other thread might read bad pos
75 else
76 { Q->extractPos++;
77 }
78 out = *(Q->extractPos);
79 return out;
80 }
81 //Q is empty
82 return NULL;
83 }
86 /*Expands the queue size automatically when it's full
87 */
88 void
89 writeAndEnlargePrivQ( void * in, PrivQueueStruc* Q )
90 {
91 void **startOfData = Q->startOfData;
92 void **endOfData = Q->endOfData;
94 void **insertPos = Q->insertPos;
95 void **extractPos = Q->extractPos;
97 tryAgain:
98 if( extractPos - insertPos != 1 &&
99 !(insertPos == endOfData && extractPos == startOfData))
100 { *(Q->insertPos) = in; //insert before move
101 if( insertPos == endOfData ) //write new pos exactly once, correctly
102 { Q->insertPos = startOfData;
103 }
104 else
105 { Q->insertPos++;
106 }
107 return;
108 }
109 //Q is full
110 enlargePrivQ( Q );
111 goto tryAgain;
112 }
115 /*Returns false when the queue was full.
116 * have option of calling make_larger_PrivQ to make more room, then try again
117 */
118 int writeAndFailPrivQ( void * in, PrivQueueStruc* Q )
119 {
120 void **startOfData = Q->startOfData;
121 void **endOfData = Q->endOfData;
123 void **insertPos = Q->insertPos;
124 void **extractPos = Q->extractPos;
126 if( extractPos - insertPos != 1 &&
127 !(insertPos == endOfData && extractPos == startOfData))
128 { *(Q->insertPos) = in; //insert before move
129 if( insertPos == endOfData ) //write new pos exactly once, correctly
130 { Q->insertPos = startOfData;
131 }
132 else
133 { Q->insertPos++;
134 }
135 return TRUE;
136 }
137 //Q is full
138 return FALSE;
139 }