view PrivateQueue.c @ 15:1ab93714b9c1

Merge pushPrivQ into VMS_malloc brch
author SeanHalle
date Thu, 11 Nov 2010 05:16:13 -0800
parents 447e97a52426 3134d8a1e8e3
children 8fd77f9430f0
line source
1 /*
2 * Copyright 2009 OpenSourceStewardshipFoundation.org
3 * Licensed under GNU General Public License version 2
4 *
5 * Author: seanhalle@yahoo.com
6 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <stdlib.h>
14 #include "PrivateQueue.h"
18 //===========================================================================
20 /*This kind of queue is private to a single core at a time -- has no
21 * synchronizations
22 */
24 PrivQueueStruc* makePrivQ()
25 {
26 PrivQueueStruc* retQ;
27 retQ = (PrivQueueStruc *) VMS__malloc( sizeof( PrivQueueStruc ) );
29 retQ->startOfData = VMS__malloc( 1024 * sizeof(void *) );
30 memset( retQ->startOfData, 0, 1024 );
32 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
33 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
34 retQ->endOfData = &(retQ->startOfData[1023]);
36 return retQ;
37 }
40 void
41 enlargePrivQ( PrivQueueStruc *Q )
42 { int oldSize, newSize;
43 void **oldStartOfData;
45 oldSize = Q->endOfData - Q->startOfData;
46 newSize = 2 * oldSize;
47 oldStartOfData = Q->startOfData;
48 Q->startOfData = VMS__malloc( newSize * sizeof(void *) );
49 memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *));
50 VMS__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 is 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 }
85 int32
86 numInPrivQ( PrivQueueStruc *Q )
87 { int32 size, numIn;
89 if( Q->insertPos < Q->extractPos )
90 { //insert has wrapped around so numIn is:
91 // insertPos + size - extractPos -- Consider, is empty when
92 // extractPos = endOfData and insert = start -- correctly get zero
93 size = Q->endOfData - Q->startOfData;
94 numIn = Q->insertPos + size - Q->extractPos;
95 }
96 else
97 {
98 numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side
99 }
100 return numIn;
101 }
104 /*Expands the queue size automatically when it's full
105 */
106 void
107 writePrivQ( void * in, PrivQueueStruc* Q )
108 {
109 void **startOfData = Q->startOfData;
110 void **endOfData = Q->endOfData;
112 void **insertPos = Q->insertPos;
113 void **extractPos = Q->extractPos;
115 tryAgain:
116 //Full? (insert is just below extract when full)
117 if( extractPos - insertPos != 1 &&
118 !(insertPos == endOfData && extractPos == startOfData))
119 { *(Q->insertPos) = in; //insert before move
120 if( insertPos == endOfData ) //write new pos exactly once, correctly
121 { Q->insertPos = startOfData;
122 }
123 else
124 { Q->insertPos++;
125 }
126 return;
127 }
128 //Q is full
129 enlargePrivQ( Q );
130 goto tryAgain;
131 }
134 /*Returns false when the queue was full.
135 * have option of calling make_larger_PrivQ to make more room, then try again
136 */
137 int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
138 {
139 void **startOfData = Q->startOfData;
140 void **endOfData = Q->endOfData;
142 void **insertPos = Q->insertPos;
143 void **extractPos = Q->extractPos;
145 if( extractPos - insertPos != 1 &&
146 !(insertPos == endOfData && extractPos == startOfData))
147 { *(Q->insertPos) = in; //insert before move
148 if( insertPos == endOfData ) //write new pos exactly once, correctly
149 { Q->insertPos = startOfData;
150 }
151 else
152 { Q->insertPos++;
153 }
154 return TRUE;
155 }
156 //Q is full
157 return FALSE;
158 }
160 /*Treats queue as a stack -- no matter contents, if read done right after
161 * a push, then the pushed item is what comes out.
162 * Expands the queue size automatically when it's full.
163 */
164 void
165 pushPrivQ( void * in, PrivQueueStruc* Q )
166 {
167 void **startOfData = Q->startOfData;
168 void **endOfData = Q->endOfData;
170 void **insertPos = Q->insertPos;
171 void **extractPos = Q->extractPos;
173 tryAgain:
174 //Full? (insert is just below extract when full)
175 if( extractPos - insertPos != 1 &&
176 !(insertPos == endOfData && extractPos == startOfData))
177 { //insert -- but go backwards, inserting at read position then
178 // move read pos backwards
179 *(Q->extractPos) = in;
180 if( extractPos == startOfData ) //write new pos exactly once, correctly
181 { Q->extractPos = endOfData; //can't overrun then fix it 'cause
182 } // other thread might read bad pos
183 else
184 { Q->extractPos--;
185 }
186 return;
187 }
188 //Q is full
189 enlargePrivQ( Q );
190 goto tryAgain;
191 }
193 void
194 freePrivQ( PrivQueueStruc *Q )
195 {
196 VMS__free( Q->startOfData );
197 VMS__free( Q );