Rleg  2
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
gqueue.c
Go to the documentation of this file.
1 /*****************************************************************************
2 // File: GQueue.c
3 // Contents: C functions for circular queue access and control.
4 // Author: G. A. Borges.
5 *****************************************************************************/
6 
7 #include <math.h>
8 #include <stdio.h>
9 
10 /* GQueue */
11 #include "gqueue.h"
12 
13 #if GQUEUE_RTAI_SUPPORT
14  #define BEGIN_ATOMIC() rt_spl_lock(&pQueueControl->SPLAtomicAccess)
15  #define END_ATOMIC() rt_spl_unlock(&pQueueControl->SPLAtomicAccess)
16 #else
17  #define BEGIN_ATOMIC()
18  #define END_ATOMIC()
19 #endif
20 
21 /*****************************************************************************
22 *** int gQUEUE_Init(PGQUEUECONTROL pQueueControl, int Size, int NReaders)
23 *** Purpose: Initialize GQUEUECONTROL structure.
24 *** Input:
25 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
26 *** - Size: length of the vector where data is stored
27 *** - NReaders: number of reading heads of the queue
28 *** Output:
29 *** - TRUE if sucess, FALSE if failure.
30 *****************************************************************************/
31 int gQUEUE_Init(PGQUEUECONTROL pQueueControl, int Size, int NReaders)
32 {
33  int n;
34 
35  if(NReaders > MAXSIZE_QUEUE_READ_GATES){
36  return FALSE;
37  }
38 
39  pQueueControl->Size = Size,
40  pQueueControl->NReaders = NReaders;
41  pQueueControl->FlagStillNotWritten = TRUE;
42  for(n=0;n<NReaders;++n){
43  pQueueControl->ReadIndex[n] = 0;
44  pQueueControl->FlagStillNotRead[n] = TRUE;
45  pQueueControl->FlagFull[n] = FALSE;
46  }
47  pQueueControl->WriteIndex = 0;
48 
49 #if GQUEUE_RTAI_SUPPORT
50  rt_spl_init(&pQueueControl->SPLAtomicAccess);
51 #endif
52  return TRUE;
53 }
54 
55 /*****************************************************************************
56 *** int gQUEUE_RequestLastReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index)
57 *** Purpose: Request the last read index, i.e., the read index corresponding the most recent
58 *** data stored in the queue. The corresponding reading pointer of GQUEUECONTROL
59 *** is updated to this value.
60 *** Input:
61 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
62 *** - NReader: number of reading head.
63 *** - *Index: pointer to an int variable on which the reading index is returned
64 *** Output:
65 *** - TRUE if sucess, FALSE if failure.
66 *****************************************************************************/
67 int gQUEUE_RequestLastReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index)
68 {
69  if(NReader>=pQueueControl->NReaders){
70  return FALSE;
71  }
72 
73  if(pQueueControl->FlagStillNotWritten == TRUE){
74  return FALSE;
75  }
76 
77 BEGIN_ATOMIC();
78 
79  if(pQueueControl->FlagStillNotRead[NReader] == TRUE){
80  pQueueControl->ReadIndex[NReader] = pQueueControl->WriteIndex;
81  *Index = pQueueControl->ReadIndex[NReader];
82  pQueueControl->FlagStillNotRead[NReader] = FALSE;
83  }
84  else{
85  if(pQueueControl->ReadIndex[NReader] == pQueueControl->WriteIndex){
86  pQueueControl->FlagFull[NReader] = FALSE;
87  *Index = -1;
88  }
89  else{
90  pQueueControl->ReadIndex[NReader] = pQueueControl->WriteIndex;
91  gQUEUE_UnwrapReadIndex(pQueueControl,NReader);
92  *Index = pQueueControl->ReadIndex[NReader];
93  }
94  }
95 
96 END_ATOMIC();
97 
98  if(*Index==-1){
99  return FALSE;
100  }
101 
102  return TRUE;
103 }
104 
105 /*****************************************************************************
106 *** int gQUEUE_RequestReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index)
107 *** Purpose: Request the next read index, i.e., the read index corresponding the next data
108 *** to be read according to the storage sequence. The corresponding reading
109 *** pointer of GQUEUECONTROL is updated to this value.
110 *** Input:
111 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
112 *** - NReader: number of reading head.
113 *** - *Index: pointer to an int variable on which the reading index is returned
114 *** Output:
115 *** - TRUE if sucess, FALSE if failure.
116 *****************************************************************************/
117 int gQUEUE_RequestReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index)
118 {
119  if(NReader>=pQueueControl->NReaders){
120  return FALSE;
121  }
122 
123  if(pQueueControl->FlagStillNotWritten == TRUE){
124  return FALSE;
125  }
126 
127 BEGIN_ATOMIC();
128  if(pQueueControl->FlagStillNotRead[NReader] == TRUE){
129  *Index = pQueueControl->ReadIndex[NReader];
130  pQueueControl->FlagStillNotRead[NReader] = FALSE;
131  }
132  else{
133  if(pQueueControl->ReadIndex[NReader] == pQueueControl->WriteIndex){
134  pQueueControl->FlagFull[NReader] = FALSE;
135  *Index = -1;
136  }
137  else{
138  ++pQueueControl->ReadIndex[NReader];
139  gQUEUE_UnwrapReadIndex(pQueueControl,NReader);
140  *Index = pQueueControl->ReadIndex[NReader];
141  }
142  }
143 END_ATOMIC();
144 
145  if(*Index==-1){
146  return FALSE;
147  }
148 
149  return TRUE;
150 }
151 
152 /*****************************************************************************
153 *** int gQUEUE_GetReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index, int IndexHorizon)
154 *** Purpose: Get the index corresponding the next-IndexHorizon data
155 *** to be read according to the storage sequence. The corresponding reading
156 *** pointer of GQUEUECONTROL is NOT updated to this value. IndexHorizon corresponds to
157 *** data which have already been read from the queue
158 *** Input:
159 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
160 *** - NReader: number of reading head.
161 *** - *Index: pointer to an int variable on which the reading index is returned
162 *** - IndexHorizon: past time horizon. If zero, Index is pointed to the next data to be read.
163 *** Output:
164 *** - TRUE if sucess, FALSE if failure.
165 *****************************************************************************/
166 int gQUEUE_GetReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int* Index, int IndexHorizon)
167 {
168  if(NReader>=pQueueControl->NReaders){
169  return FALSE;
170  }
171 
172  if(pQueueControl->FlagStillNotWritten == TRUE){
173  return FALSE;
174  }
175 
176 BEGIN_ATOMIC();
177 
178  *Index = (pQueueControl->ReadIndex[NReader]-IndexHorizon);
179  if(*Index<0){
180  *Index += pQueueControl->Size;
181  }
182  gQUEUE_UnwrapReadIndex(pQueueControl, NReader);
183 
184 END_ATOMIC();
185 
186 
187  return TRUE;
188 }
189 
190 /*****************************************************************************
191 *** int gQUEUE_GetWriteIndex(PGQUEUECONTROL pQueueControl, int* Index, int IndexHorizon)
192 *** Purpose: Get the index corresponding the next-IndexHorizon data
193 *** to be write according to the storage sequence. The corresponding writing
194 *** pointer of GQUEUECONTROL is NOT updated to this value. IndexHorizon corresponds to
195 *** data which have already been stored to the queue
196 *** Input:
197 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
198 *** - *Index: pointer to an int variable on which the reading index is returned
199 *** - IndexHorizon: past time horizon. If zero, Index is pointed to the next data to be written.
200 *** Output:
201 *** - TRUE if sucess, FALSE if failure.
202 *****************************************************************************/
203 int gQUEUE_GetWriteIndex(PGQUEUECONTROL pQueueControl, int* Index, int IndexHorizon)
204 {
205 
206  if(pQueueControl->FlagStillNotWritten == TRUE){
207  return FALSE;
208  }
209 
210 BEGIN_ATOMIC();
211 
212  *Index = (pQueueControl->WriteIndex-IndexHorizon);
213  if(*Index<0){
214  *Index += pQueueControl->Size;
215  }
216  gQUEUE_UnwrapWriteIndex(pQueueControl);
217 
218 END_ATOMIC();
219 
220  return TRUE;
221 }
222 
223 /*****************************************************************************
224 *** int gQUEUE_RequestWriteIndex(PGQUEUECONTROL pQueueControl, int* Index)
225 *** Purpose: Request the next data storage index in the queue. The corresponding writing
226 *** pointer of GQUEUECONTROL is updated to this value.
227 *** Input:
228 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
229 *** - *Index: pointer to an int variable on which the writing index is returned
230 *** Output:
231 *** - TRUE if sucess, FALSE if the queue is full for some reading head.
232 *****************************************************************************/
233 int gQUEUE_RequestWriteIndex(PGQUEUECONTROL pQueueControl, int* Index)
234 {
235  int n;
236  int FlagNotFull = TRUE;
237 
238 BEGIN_ATOMIC();
239 
240  if(pQueueControl->FlagStillNotWritten == TRUE){
241  *Index = pQueueControl->WriteIndex;
242  pQueueControl->FlagStillNotWritten = FALSE;
243  }
244  else{
245  /* Increment write index in two positions to test if queue is full */
246  pQueueControl->WriteIndex += 2;
247  gQUEUE_UnwrapWriteIndex(pQueueControl);
248 
249  for(n=0;n<pQueueControl->NReaders;++n){
250  if(pQueueControl->ReadIndex[n] == pQueueControl->WriteIndex){
251  pQueueControl->FlagFull[n] = TRUE;
252  FlagNotFull = FALSE;
253  }
254  }
255 
256  /* Decrement write index of one position to return to the correct state */
257  pQueueControl->WriteIndex += pQueueControl->Size-1;
258  gQUEUE_UnwrapWriteIndex(pQueueControl);
259 
260  *Index = pQueueControl->WriteIndex;
261  }
262 
263 END_ATOMIC();
264 
265  return FlagNotFull;
266 }
267 
268 /*****************************************************************************
269 *** int gQUEUE_UnwrapReadIndex(PGQUEUECONTROL pQueueControl, int NReader)
270 *** Purpose: Unwrap the read index in such way that it points to any valid value in the queue.
271 *** Input:
272 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
273 *** - NReader: number of the reading head.
274 *** Output:
275 *** - TRUE if sucess, FALSE if failure.
276 *****************************************************************************/
277 int gQUEUE_UnwrapReadIndex(PGQUEUECONTROL pQueueControl, int NReader)
278 {
279  if(NReader>=pQueueControl->NReaders){
280  return FALSE;
281  }
282 
283  pQueueControl->ReadIndex[NReader] = (pQueueControl->ReadIndex[NReader]) % (pQueueControl->Size);
284 
285  return TRUE;
286 }
287 
288 /*****************************************************************************
289 *** int gQUEUE_UnwrapWriteIndex(PGQUEUECONTROL pQueueControl)
290 *** Purpose: Unwrap the write index in such way that it points to any valid value in the queue.
291 *** Input:
292 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
293 *** - NReader: number of the reading head.
294 *** Output:
295 *** - TRUE if sucess, FALSE if failure.
296 *****************************************************************************/
298 {
299  pQueueControl->WriteIndex = (pQueueControl->WriteIndex) % (pQueueControl->Size);
300 
301  return TRUE;
302 }
303 
304 /*****************************************************************************
305 *** int gQUEUE_GetNumberOfUnreadData(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
306 *** Purpose: Returns the number of unread data stored associated to a given reading head.
307 *** Input:
308 *** - pQueueControl: pointer to GQUEUECONTROL structure associated to the queue
309 *** - NReader: number of the reading head
310 *** - *Index: pointer to an int where the number of unread data is stored
311 *** Output:
312 *** - TRUE if sucess, FALSE if failure.
313 *****************************************************************************/
314 int gQUEUE_GetNumberOfUnreadData(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
315 {
316  if(NReader>=pQueueControl->NReaders){
317  return FALSE;
318  }
319 
320  if(pQueueControl->WriteIndex >= pQueueControl->ReadIndex[NReader]){
321  *Index = pQueueControl->WriteIndex-pQueueControl->ReadIndex[NReader];
322  }
323  else{
324  *Index = pQueueControl->Size-(pQueueControl->ReadIndex[NReader]-pQueueControl->WriteIndex);
325  }
326 
327  return TRUE;
328 }
int gQUEUE_UnwrapWriteIndex(PGQUEUECONTROL pQueueControl)
Definition: gqueue.c:297
int FlagFull[MAXSIZE_QUEUE_READ_GATES]
Definition: gqueue.h:45
#define FALSE
#define END_ATOMIC()
Definition: gqueue.c:18
int gQUEUE_UnwrapReadIndex(PGQUEUECONTROL pQueueControl, int NReader)
Definition: gqueue.c:277
#define BEGIN_ATOMIC()
Definition: gqueue.c:17
int WriteIndex
Definition: gqueue.h:38
int gQUEUE_GetReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int *Index, int IndexHorizon)
Definition: gqueue.c:166
#define TRUE
int gQUEUE_GetWriteIndex(PGQUEUECONTROL pQueueControl, int *Index, int IndexHorizon)
Definition: gqueue.c:203
int gQUEUE_RequestLastReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
Definition: gqueue.c:67
int FlagStillNotRead[MAXSIZE_QUEUE_READ_GATES]
Definition: gqueue.h:44
int FlagStillNotWritten
Definition: gqueue.h:43
int NReaders
Definition: gqueue.h:42
int ReadIndex[MAXSIZE_QUEUE_READ_GATES]
Definition: gqueue.h:37
int gQUEUE_RequestWriteIndex(PGQUEUECONTROL pQueueControl, int *Index)
Definition: gqueue.c:233
int gQUEUE_GetNumberOfUnreadData(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
Definition: gqueue.c:314
int gQUEUE_RequestReadIndex(PGQUEUECONTROL pQueueControl, int NReader, int *Index)
Definition: gqueue.c:117
int gQUEUE_Init(PGQUEUECONTROL pQueueControl, int Size, int NReaders)
Definition: gqueue.c:31
#define MAXSIZE_QUEUE_READ_GATES
Definition: gqueue.h:22
int Size
Definition: gqueue.h:36