view PrivateQueue.c @ 24:677afc259a58

fix branch to compile with new folder structure
author Merten Sach <msach@mailbox.tu-berlin.de>
date Mon, 13 Feb 2012 19:32:12 +0100
parents 7c9e00ff1bf4
children
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"
15 #include "VMS_Implementations/VMS_impl/vmalloc.h"
19 //===========================================================================
21 /*This kind of queue is private to a single core at a time -- has no
22 * synchronizations
23 */
25 PrivQueueStruc* makePrivQ()
26 {
27 PrivQueueStruc *retQ;
28 retQ = VMS_int__malloc( sizeof( PrivQueueStruc ) );
29 retQ->startOfData = (void*)VMS_int__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 { size_t oldSize, newSize;
43 void **oldStartOfData;
45 oldSize = Q->endOfData - Q->startOfData + 1;
46 newSize = 2 * oldSize;
47 oldStartOfData = Q->startOfData;
48 Q->startOfData = VMS_int__malloc( newSize * sizeof(void*));
49 //copy second half
50 size_t secondHalfSize = Q->endOfData - Q->extractPos + 1;
51 memcpy(Q->startOfData,Q->extractPos, secondHalfSize * sizeof(void*));
52 //copy first half
53 memcpy(Q->startOfData + secondHalfSize, oldStartOfData,
54 (oldSize-secondHalfSize) * sizeof(void*));
55 VMS_int__free(oldStartOfData);
57 Q->extractPos = Q->startOfData;
58 Q->insertPos = Q->startOfData + oldSize - 1;
59 Q->endOfData = &(Q->startOfData[newSize - 1]);
60 }
63 /*Returns NULL when queue is empty
64 */
65 void* readPrivQ( PrivQueueStruc* Q )
66 { void *out = 0;
67 void **startOfData = Q->startOfData;
68 void **endOfData = Q->endOfData;
70 void **insertPos = Q->insertPos;
71 void **extractPos = Q->extractPos;
73 //if not empty -- (extract is just below insert when empty)
74 if( insertPos - extractPos != 1 &&
75 !(extractPos == endOfData && insertPos == startOfData))
76 { //move before read
77 if( extractPos == endOfData ) //write new pos exactly once, correctly
78 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
79 } // other thread might read bad pos
80 else
81 { Q->extractPos++;
82 }
83 out = *(Q->extractPos);
84 return out;
85 }
86 //Q is empty
87 return NULL;
88 }
90 int32
91 numInPrivQ( PrivQueueStruc *Q )
92 { int32 size, numIn;
94 if( Q->insertPos < Q->extractPos )
95 { //insert has wrapped around so numIn is:
96 // insertPos + size - extractPos -- Consider, is empty when
97 // extractPos = endOfData and insert = start -- correctly get zero
98 size = Q->endOfData - Q->startOfData;
99 numIn = Q->insertPos + size - Q->extractPos;
100 }
101 else
102 {
103 numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side
104 }
105 return numIn;
106 }
109 /*Expands the queue size automatically when it's full
110 */
111 void
112 writePrivQ( void * in, PrivQueueStruc* Q )
113 {
114 while(1){
115 void **startOfData = Q->startOfData;
116 void **endOfData = Q->endOfData;
118 void **insertPos = Q->insertPos;
119 void **extractPos = Q->extractPos;
121 //Full? (insert is just below extract when full)
122 if( extractPos - insertPos != 1 &&
123 !(insertPos == endOfData && extractPos == startOfData))
124 { *(Q->insertPos) = in; //insert before move
125 if( insertPos == endOfData ) //write new pos exactly once, correctly
126 { Q->insertPos = startOfData;
127 }
128 else
129 { Q->insertPos++;
130 }
131 return;
132 }
133 //Q is full
134 enlargePrivQ( Q );
135 }
136 }
139 /*Returns false when the queue was full.
140 * have option of calling make_larger_PrivQ to make more room, then try again
141 */
142 int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
143 {
144 void **startOfData = Q->startOfData;
145 void **endOfData = Q->endOfData;
147 void **insertPos = Q->insertPos;
148 void **extractPos = Q->extractPos;
150 if( extractPos - insertPos != 1 &&
151 !(insertPos == endOfData && extractPos == startOfData))
152 { *(Q->insertPos) = in; //insert before move
153 if( insertPos == endOfData ) //write new pos exactly once, correctly
154 { Q->insertPos = startOfData;
155 }
156 else
157 { Q->insertPos++;
158 }
159 return TRUE;
160 }
161 //Q is full
162 return FALSE;
163 }
165 /*Treats queue as a stack -- no matter contents, if read done right after
166 * a push, then the pushed item is what comes out.
167 * Expands the queue size automatically when it's full.
168 */
169 void
170 pushPrivQ( void * in, PrivQueueStruc* Q )
171 {
172 while(1){
173 void **startOfData = Q->startOfData;
174 void **endOfData = Q->endOfData;
176 void **insertPos = Q->insertPos;
177 void **extractPos = Q->extractPos;
179 //Full? (insert is just below extract when full)
180 if( extractPos - insertPos != 1 &&
181 !(insertPos == endOfData && extractPos == startOfData))
182 { //insert -- but go backwards, inserting at read position then
183 // move read pos backwards
184 *(Q->extractPos) = in;
185 if( extractPos == startOfData ) //write new pos exactly once, correctly
186 { Q->extractPos = endOfData; //can't overrun then fix it 'cause
187 } // other thread might read bad pos
188 else
189 { Q->extractPos--;
190 }
191 return;
192 }
193 //Q is full
194 enlargePrivQ( Q );
195 }
196 }
198 void
199 freePrivQ( PrivQueueStruc *Q )
200 {
201 VMS_int__free( Q->startOfData );
202 VMS_int__free( Q );