comparison PrivateQueue.c @ 41:8fcbe46de60a

bugfixes - peek and enlarge now working properly
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Wed, 19 Dec 2012 15:38:08 +0100
parents b9cb01d8ce56
children c54f7e0a9d11
comparison
equal deleted inserted replaced
23:f63ccb59d744 24:8b6ec6c1dea5
6 * 6 *
7 * Author: seanhalle@yahoo.com 7 * Author: seanhalle@yahoo.com
8 */ 8 */
9 9
10 10
11 #include <string.h>
12 #include <stdlib.h>
11 #include <stdio.h> 13 #include <stdio.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <stdlib.h>
15 14
16 #include "PrivateQueue.h" 15 #include "PrivateQueue.h"
17 16
18 17
19 18
34 memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); 33 memset( retQ->startOfData, 0, 1024 * sizeof(void *) );
35 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty 34 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
36 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be 35 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
37 retQ->endOfData = &(retQ->startOfData[1023]); 36 retQ->endOfData = &(retQ->startOfData[1023]);
38 37
38 #ifdef DEBUG_PRIVATE_Q
39 retQ->numReads = 0;
40 retQ->numWrites =0;
41 #endif
42
39 return retQ; 43 return retQ;
40 } 44 }
41 45
42 46
43 void 47 void
44 enlargePrivQ( PrivQueueStruc *Q ) 48 enlargePrivQ( PrivQueueStruc *Q )
45 { int32 oldSize, newSize, topPartSize, bottPartSize; 49 { size_t oldSize, newSize, topPartSize, bottPartSize;
46 int8 *insertPos, *extractPos; 50 char *insertPos, *extractPos;
47 int8 *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData; 51 char *oldStartOfData, *oldEndOfData, *newStartOfData, *newEndOfData;
48 int32 insertOffsetBytes, extractOffsetBytes; 52 size_t insertOffsetBytes, extractOffsetBytes;
49 int8 *copyStartAddr; 53 char* copyStartAddr;
50 54
51 oldStartOfData = (int8 *)Q->startOfData; 55 #ifdef DEBUG_PRIVATE_Q
52 oldEndOfData = (int8 *)Q->endOfData; 56 printf("Enlarging queue Q = %p\nnumReads = %d; numWrites = %d\n",Q,Q->numReads,Q->numWrites);
53 insertPos = (int8 *)Q->insertPos; 57 #endif
54 extractPos = (int8 *)Q->extractPos; 58
59 oldStartOfData = (char*)Q->startOfData;
60 oldEndOfData = (char*)(Q->endOfData + 1);
61 insertPos = (char*)Q->insertPos;
62 extractPos = (char*)Q->extractPos;
55 63
56 //TODO: verify these get number of bytes correct 64 //TODO: verify these get number of bytes correct
57 insertOffsetBytes = (int32)(insertPos - oldStartOfData); 65 insertOffsetBytes = (insertPos - oldStartOfData);
58 extractOffsetBytes = (int32)(extractPos - oldStartOfData); 66 extractOffsetBytes = (extractPos - oldStartOfData);
59 67
60 oldSize = oldEndOfData - oldStartOfData + 1; //in bytes 68 oldSize = oldEndOfData - oldStartOfData; //in bytes
61 newSize = 2 * oldSize; 69 newSize = 2 * oldSize;
62 70
71 #ifdef DEBUG_PRIVATE_Q
72 printf("Old size = %d, new size = %d\n",(int)oldSize,(int)newSize);
73 #endif
74
63 //This malloc is not safe to use in wrapper lib nor app code! 75 //This malloc is not safe to use in wrapper lib nor app code!
64 Q->startOfData = (void **)VMS_int__malloc( newSize ); 76 newStartOfData = (char *) VMS_int__malloc( newSize );
65 newStartOfData = (int8 *)Q->startOfData; 77 if(newStartOfData == NULL){
78 perror("malloc"); exit(1);
79 }
66 newEndOfData = newStartOfData + newSize; //all calcs in Bytes 80 newEndOfData = newStartOfData + newSize; //all calcs in Bytes
67 Q->endOfData = (void **)newEndOfData; 81
68
69 //TODO: test all of this, for both cases 82 //TODO: test all of this, for both cases
70 83 Q->startOfData = newStartOfData;
84 Q->endOfData = ((void **)newEndOfData) - 1;
85
71 //Moving the data and pointers to the new array is 86 //Moving the data and pointers to the new array is
72 //a little trickier than at first it seems.. the top part 87 //a little trickier than at first it seems.. the top part
73 // of old queue must be moved to the top part of new queue, while 88 // of old queue must be moved to the top part of new queue, while
74 // bottom part of old to bottom part of new, then the new insert 89 // bottom part of old to bottom part of new, then the new insert
75 // and extract positions calculated by offset from top and bottom 90 // and extract positions calculated by offset from top and bottom
76 //UNLESS the one case where old extract was at bottom and insert 91 //UNLESS the one case where old extract was at bottom and insert
77 // was at top. 92 // was at top.
78 //TODO: check that this is correct! 93 //TODO: check that this is correct!
79 if( extractPos == oldStartOfData && insertPos == oldEndOfData ) 94 if( extractPos == oldStartOfData )
80 { 95 {
81 memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes 96 memcpy( newStartOfData, oldStartOfData, oldSize ); //oldSize is bytes
82 Q->extractPos = Q->startOfData; //start of valid data 97 Q->extractPos = Q->startOfData; //start of valid data
83 Q->insertPos = Q->startOfData + oldSize - 1; //end of valid data 98 Q->insertPos = (void**)(newStartOfData + insertOffsetBytes); //end of valid data
84 } 99 }
85 else //have to copy two parts separately, then calc positions 100 else //have to copy two parts separately, then calc positions
86 { //TODO: check end-addr, sizes, and new positions carefully 101 { //TODO: check end-addr, sizes, and new positions carefully
87 102
88 //copy top part, starting at extract up until end of data, 103 //copy top part, starting at extract up until end of data,
89 // into top of new array 104 // into top of new array
90 topPartSize = oldEndOfData - extractPos + 1; //+1 includes extractPos 105 topPartSize = oldEndOfData - extractPos;
91 copyStartAddr = newEndOfData - topPartSize + 1;//+1 cancels other 106 copyStartAddr = newEndOfData - topPartSize;
92 memcpy( copyStartAddr, Q->extractPos, topPartSize ); 107 memcpy( copyStartAddr, extractPos, topPartSize );
93 Q->extractPos = (void **)copyStartAddr; //extract just-copied data 108 Q->extractPos = (void **)copyStartAddr; //extract just-copied data
94 109
95 //copy bottom part, from old start up to old insert, 110 //copy bottom part, from old start up to old insert,
96 // into bottom of new array 111 // into bottom of new array
97 bottPartSize = oldSize - topPartSize - 1; //-1 for empty insertPos 112 bottPartSize = insertPos - oldStartOfData; //-1 for empty insertPos
98 memcpy( newStartOfData, oldStartOfData, bottPartSize ); 113 memcpy( newStartOfData, oldStartOfData, bottPartSize );
99 Q->insertPos = (void **)(newStartOfData + bottPartSize); 114 Q->insertPos = (void **)(newStartOfData + bottPartSize);
100 } 115 }
101 //This free is not safe to use in wrapper lib nor app code! 116 //This free is not safe to use in wrapper lib nor app code!
102 VMS_int__free(oldStartOfData); 117 VMS_int__free(oldStartOfData);
135 150
136 //if not empty -- (extract is just below insert when empty) 151 //if not empty -- (extract is just below insert when empty)
137 if( insertPos - extractPos != 1 && 152 if( insertPos - extractPos != 1 &&
138 !(extractPos == endOfData && insertPos == startOfData)) 153 !(extractPos == endOfData && insertPos == startOfData))
139 { 154 {
140 out = *(Q->extractPos); 155 out = *(Q->extractPos + 1);
141 return out; 156 return out;
142 } 157 }
143 //Q is empty 158 //Q is empty
144 return NULL; 159 return NULL;
145 } 160 }
146 161
147
148 /*Returns NULL when queue is empty 162 /*Returns NULL when queue is empty
149 */ 163 */
150 void* readPrivQ( PrivQueueStruc* Q ) 164 void* readPrivQ(PrivQueueStruc* Q) {
151 { void *out = 0; 165 #ifdef DEBUG_PRIVATE_Q
152 void **startOfData = Q->startOfData; 166 Q->numReads++;
153 void **endOfData = Q->endOfData; 167 #endif
154 168
155 void **insertPos = Q->insertPos; 169 void *out = 0;
156 void **extractPos = Q->extractPos; 170 void **startOfData = Q->startOfData;
157 171 void **endOfData = Q->endOfData;
158 //if not empty -- (extract is just below insert when empty) 172
159 if( insertPos - extractPos != 1 && 173 void **insertPos = Q->insertPos;
160 !(extractPos == endOfData && insertPos == startOfData)) 174 void **extractPos = Q->extractPos;
161 { //move before read 175
162 if( extractPos == endOfData ) //write new pos exactly once, correctly 176 //if not empty -- (extract is just below insert when empty)
163 { Q->extractPos = startOfData; //can't overrun then fix it 'cause 177 if (insertPos - extractPos != 1 &&
164 } // other thread might read bad pos 178 !(extractPos == endOfData && insertPos == startOfData)) { //move before read
165 else 179 if (extractPos == endOfData) //write new pos exactly once, correctly
166 { Q->extractPos++; 180 {
167 } 181 Q->extractPos = startOfData; //can't overrun then fix it 'cause
168 out = *(Q->extractPos); 182 }// other thread might read bad pos
169 return out; 183 else {
170 } 184 Q->extractPos++;
171 //Q is empty 185 }
172 return NULL; 186 out = *(Q->extractPos);
173 } 187 return out;
174 188 }
175 189 //Q is empty
190 return NULL;
191 }
176 /*Expands the queue size automatically when it's full 192 /*Expands the queue size automatically when it's full
177 */ 193 */
178 void 194 void
179 writePrivQ( void * in, PrivQueueStruc* Q ) 195 writePrivQ(void * in, PrivQueueStruc* Q) {
196
197 #ifdef DEBUG_PRIVATE_Q
198 Q->numWrites++;
199 #endif
200
201 //tryAgain:
202 //Full? (insert is just below extract when full)
203 if ((Q->extractPos - Q->insertPos) == 1 ||
204 (Q->insertPos == Q->endOfData && Q->extractPos == Q->startOfData)) {
205 enlargePrivQ(Q);
206 }
207
208 *(Q->insertPos) = in; //insert before move
209 if (Q->insertPos == Q->endOfData) //write new pos exactly once, correctly
210 {
211 Q->insertPos = Q->startOfData;
212 } else {
213 Q->insertPos++;
214 }
215 return;
216
217 //Q is full
218
219 //goto tryAgain;
220 }
221
222
223 /*Returns false when the queue was full.
224 * have option of calling make_larger_PrivQ to make more room, then try again
225 */
226 bool32
227 writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
180 { 228 {
181 void **startOfData = Q->startOfData; 229 void **startOfData = Q->startOfData;
182 void **endOfData = Q->endOfData; 230 void **endOfData = Q->endOfData;
183 231
184 void **insertPos = Q->insertPos; 232 void **insertPos = Q->insertPos;
185 void **extractPos = Q->extractPos; 233 void **extractPos = Q->extractPos;
186 234
187 tryAgain:
188 //Full? (insert is just below extract when full)
189 if( extractPos - insertPos != 1 && 235 if( extractPos - insertPos != 1 &&
190 !(insertPos == endOfData && extractPos == startOfData)) 236 !(insertPos == endOfData && extractPos == startOfData))
191 { *(Q->insertPos) = in; //insert before move 237 { *(Q->insertPos) = in; //insert before move
192 if( insertPos == endOfData ) //write new pos exactly once, correctly 238 if( insertPos == endOfData ) //write new pos exactly once, correctly
193 { Q->insertPos = startOfData; 239 { Q->insertPos = startOfData;
194 } 240 }
195 else 241 else
196 { Q->insertPos++; 242 { Q->insertPos++;
197 } 243 }
198 return; 244 #ifdef DEBUG_PRIVATE_Q
199 } 245 Q->numWrites++;
200 //Q is full 246 #endif
201 enlargePrivQ( Q );
202 goto tryAgain;
203 }
204
205
206 /*Returns false when the queue was full.
207 * have option of calling make_larger_PrivQ to make more room, then try again
208 */
209 bool32
210 writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
211 {
212 void **startOfData = Q->startOfData;
213 void **endOfData = Q->endOfData;
214
215 void **insertPos = Q->insertPos;
216 void **extractPos = Q->extractPos;
217
218 if( extractPos - insertPos != 1 &&
219 !(insertPos == endOfData && extractPos == startOfData))
220 { *(Q->insertPos) = in; //insert before move
221 if( insertPos == endOfData ) //write new pos exactly once, correctly
222 { Q->insertPos = startOfData;
223 }
224 else
225 { Q->insertPos++;
226 }
227 return TRUE; 247 return TRUE;
228 } 248 }
229 //Q is full 249 //Q is full
230 return FALSE; 250 return FALSE;
231 } 251 }
254 * Expands the queue size automatically when it's full. 274 * Expands the queue size automatically when it's full.
255 */ 275 */
256 void 276 void
257 pushPrivQ( void * in, PrivQueueStruc* Q ) 277 pushPrivQ( void * in, PrivQueueStruc* Q )
258 { 278 {
279 #ifdef DEBUG_PRIVATE_Q
280 Q->numWrites++;
281 #endif
259 while(1){ 282 while(1){
260 void **startOfData = Q->startOfData; 283 void **startOfData = Q->startOfData;
261 void **endOfData = Q->endOfData; 284 void **endOfData = Q->endOfData;
262 285
263 void **insertPos = Q->insertPos; 286 void **insertPos = Q->insertPos;