]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/LibC/Containers/Queues/Fifo.c
347ac02fd2e2a3ac2f2ca4d7223234c9ed5041a3
2 Class for arbitrary sized FIFO queues.
4 The FIFO is empty if both the Read and Write indexes are equal.
5 The FIFO is full if the next write would make the Read and Write indexes equal.
7 Member variable NumElements is the maximum number of elements that can be
9 If NumElements is ZERO, there is an error.
10 NumElements should be in the range 1:N.
12 Members WriteIndex and ReadIndex are indexes into the array implementing the
13 FIFO. They should be in the range 0:(NumElements - 1).
15 One element of the FIFO is always reserved as the "terminator" element. Thus,
16 the capacity of a FIFO is actually NumElements-1.
18 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
19 This program and the accompanying materials are licensed and made available
20 under the terms and conditions of the BSD License which accompanies this
21 distribution. The full text of the license may be found at
22 http://opensource.org/licenses/bsd-license.php.
24 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
25 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 #include <Library/BaseLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/MemoryAllocationLib.h>
32 #include <LibConfig.h>
39 #include <Containers/Fifo.h>
41 /** Determine number of items available to read from the FIFO.
43 The number of items are either the number of bytes, or the number of elements
44 depending upon the value of the As enumerator.
46 @param[in] Self Pointer to the FIFO instance.
47 @param[in] As An enumeration variable whose value determines whether the
48 returned value is the number of bytes or the number of elements
49 currently contained by the FIFO.
51 @retval 0 The FIFO is empty.
52 @retval >=0 The number of items contained by the FIFO.
64 if(Self
->ReadIndex
<= Self
->WriteIndex
) {
65 Count
= Self
->WriteIndex
- Self
->ReadIndex
;
68 Count
= Self
->NumElements
- (Self
->ReadIndex
- Self
->WriteIndex
);
71 Count
*= Self
->ElementSize
;
76 /** Determine amount of free space in the FIFO that can be written into.
78 The number of items are either the number of bytes, or the number of elements
79 depending upon the value of the As enumerator.
81 @param[in] Self Pointer to the FIFO instance.
82 @param[in] As An enumeration variable whose value determines whether the
83 returned value is the number of bytes or the number of elements
84 currently available in the FIFO.
86 @retval 0 The FIFO is full.
87 @retval >=0 The number of items which can be accepted by the FIFO.
101 RDex
= Self
->ReadIndex
;
102 WDex
= Self
->WriteIndex
;
105 Count
= Self
->NumElements
- ((WDex
- RDex
) - 1);
108 Count
= (RDex
- WDex
);
111 Count
*= Self
->ElementSize
;
116 /** Reduce the FIFO contents by NumElem elements.
118 @param[in] Self Pointer to the FIFO instance.
119 @param[in] NumElem Number of elements to delete from the FIFO.
121 @retval 0 FIFO is now empty.
122 @retval N>0 There are still N elements in the FIFO.
123 @retval -1 There are fewer than NumElem elements in the FIFO.
135 assert(Self
!= NULL
);
137 QCount
= FIFO_NumInQueue(Self
, AsElements
);
138 if(NumElem
> QCount
) {
143 RetVal
= (ssize_t
)ModuloAdd(Self
->ReadIndex
, (UINT32
)NumElem
, Self
->NumElements
);
144 Self
->ReadIndex
= (UINT32
)RetVal
;
146 RetVal
= (ssize_t
)(QCount
- NumElem
);
151 /** Test whether the FIFO is empty.
153 @param[in] Self Pointer to the FIFO instance.
155 @retval TRUE The FIFO is empty.
156 @retval FALSE There is data in the FIFO.
165 assert(Self
!= NULL
);
167 return (BOOLEAN
)(Self
->WriteIndex
== Self
->ReadIndex
);
170 /** Test whether the FIFO is full.
172 @param[in] Self Pointer to the FIFO instance.
174 @retval TRUE The FIFO is full.
175 @retval FALSE There is free space in the FIFO.
184 assert(Self
!= NULL
);
186 return (BOOLEAN
)(ModuloIncrement(Self
->WriteIndex
, Self
->NumElements
) == (INT32
)Self
->ReadIndex
);
189 /** Add one or more elements to the FIFO.
191 This function allows one to add one or more elements, as specified by Count,
192 to the FIFO. Each element is of the size specified when the FIFO object
193 was instantiated (FIFO.ElementSize).
195 pElement points to the first byte of the first element to be added.
196 If multiple elements are to be added, the elements are expected to be
197 organized as a packed array.
199 @param[in] Self Pointer to the FIFO instance.
200 @param[in] pElement Pointer to the element(s) to enqueue (add).
201 @param[in] Count Number of elements to add.
203 @retval 0 The FIFO is full.
204 @retval >=0 The number of elements added to the FIFO.
211 const void *pElement
,
218 UINT32 SizeOfElement
;
221 assert(Self
!= NULL
);
222 assert(pElement
!= NULL
);
225 if(FIFO_IsFull(Self
)) {
229 Count
= MIN(Count
, Self
->FreeSpace(Self
, AsElements
));
230 SizeOfElement
= Self
->ElementSize
;
231 Windex
= Self
->WriteIndex
;
233 ElemPtr
= (uintptr_t)pElement
;
235 QPtr
= (uintptr_t)Self
->Queue
+ (SizeOfElement
* Windex
);
236 for(i
= 0; i
< Count
; ++i
) {
237 (void)CopyMem((void *)QPtr
, (const void *)ElemPtr
, SizeOfElement
);
238 Windex
= (UINT32
)ModuloIncrement(Windex
, Self
->NumElements
);
239 if(Windex
== 0) { // If the index wrapped
240 QPtr
= (uintptr_t)Self
->Queue
;
243 QPtr
+= SizeOfElement
;
245 ElemPtr
+= SizeOfElement
;
247 (void)ZeroMem((void*)QPtr
, SizeOfElement
);
248 Self
->WriteIndex
= Windex
;
253 /** Read or copy elements from the FIFO.
255 This function allows one to read one or more elements, as specified by Count,
256 from the FIFO. Each element is of the size specified when the FIFO object
257 was instantiated (FIFO.ElementSize).
259 pElement points to the destination of the first byte of the first element
260 to be read. If multiple elements are to be read, the elements are expected
261 to be organized as a packed array.
263 @param[in] Self Pointer to the FIFO instance.
264 @param[out] pElement Pointer to where to store the element(s) read from the FIFO.
265 @param[in] Count Number of elements to dequeue.
266 @param[in] Consume If TRUE, consume read elements. Otherwise, preserve.
268 @retval 0 The FIFO is empty.
269 @retval >=0 The number of elements read from the FIFO.
284 UINT32 SizeOfElement
;
287 assert(Self
!= NULL
);
288 assert(pElement
!= NULL
);
291 if(FIFO_IsEmpty(Self
)) {
295 RDex
= Self
->ReadIndex
;
296 SizeOfElement
= Self
->ElementSize
;
297 ElemPtr
= (UINTN
)pElement
;
298 Count
= MIN(Count
, Self
->Count(Self
, AsElements
));
300 QPtr
= (UINTN
)Self
->Queue
+ (RDex
* Self
->ElementSize
);
301 for(i
= 0; i
< Count
; ++i
) {
302 (void)CopyMem((void *)ElemPtr
, (const void *)QPtr
, Self
->ElementSize
);
303 RDex
= (UINT32
)ModuloIncrement(RDex
, Self
->NumElements
);
304 if(RDex
== 0) { // If the index wrapped
305 QPtr
= (UINTN
)Self
->Queue
;
308 QPtr
+= Self
->ElementSize
;
310 ElemPtr
+= Self
->ElementSize
;
313 Self
->ReadIndex
= RDex
;
319 /** Read elements from the FIFO.
321 @param[in] Self Pointer to the FIFO instance.
322 @param[out] pElement Pointer to where to store the element read from the FIFO.
323 @param[in] Count Number of elements to dequeue.
325 @retval 0 The FIFO is empty.
326 @retval >=0 The number of elements read from the FIFO.
337 return FIFO_Dequeue(Self
, pElement
, Count
, TRUE
);
340 /** Make a copy of the FIFO's data.
341 The contents of the FIFO is copied out and linearized without affecting the
344 @param[in] Self Pointer to the FIFO instance.
345 @param[out] pElement Pointer to where to store the elements copied from the FIFO.
346 @param[in] Count Number of elements to copy.
348 @retval 0 The FIFO is empty.
349 @retval >=0 The number of elements copied from the FIFO.
360 return FIFO_Dequeue(Self
, pElement
, Count
, FALSE
);
363 /** Get the FIFO's current Read Index.
365 @param[in] Self Pointer to the FIFO instance.
374 assert(Self
!= NULL
);
376 return Self
->ReadIndex
;
379 /** Get the FIFO's current Write Index.
381 @param[in] Self Pointer to the FIFO instance.
383 @return The current value of the FIFO's WriteIndex member is returned.
392 assert(Self
!= NULL
);
394 return Self
->WriteIndex
;
397 /** Cleanly delete a FIFO instance.
399 @param[in] Self Pointer to the FIFO instance.
408 assert(Self
!= NULL
);
410 if(Self
->Queue
!= NULL
) {
411 FreePool(Self
->Queue
);
412 Self
->Queue
= NULL
; // Zombie catcher
417 /** Empty the FIFO, discarding up to NumToFlush elements.
419 @param[in] Self Pointer to the FIFO instance.
420 @param[in] NumToFlush Number of elements to flush from the FIFO.
421 If larger than the number of elements in the
422 FIFO, the FIFO is emptied.
424 @return Returns the number of elements remaining in the FIFO after the flush.
437 assert(Self
!= NULL
);
439 NumInQ
= FIFO_FreeSpace(Self
, AsElements
);
440 if(NumToFlush
>= NumInQ
) {
442 Self
->WriteIndex
= 0;
446 Remainder
= FIFO_Reduce(Self
, NumToFlush
);
451 /** Remove the most recently added element from the FIFO.
453 @param[in] Self Pointer to the FIFO instance.
455 @return Returns the number of elements remaining in the FIFO.
466 assert(Self
!= NULL
);
468 Remainder
= Self
->Count(Self
, AsElements
);
470 Self
->WriteIndex
= (UINT32
)ModuloDecrement(Self
->WriteIndex
, Self
->NumElements
);
476 /** Construct a new instance of a FIFO Queue.
478 @param[in] NumElements Number of elements to be contained in the new FIFO.
479 @param[in] ElementSize Size, in bytes, of an element.
481 @retval NULL Unable to create the instance.
482 @retval NonNULL Pointer to the new FIFO instance.
495 if((NumElements
> 2) && (ElementSize
> 0)) {
496 FIFO
= (cFIFO
*)AllocatePool(sizeof(cFIFO
));
498 Queue
= (UINT8
*)AllocateZeroPool(NumElements
* ElementSize
);
500 FIFO
->Write
= FIFO_Enqueue
;
501 FIFO
->Read
= FIFO_Read
;
502 FIFO
->Copy
= FIFO_Copy
;
503 FIFO
->IsEmpty
= FIFO_IsEmpty
;
504 FIFO
->IsFull
= FIFO_IsFull
;
505 FIFO
->Count
= FIFO_NumInQueue
;
506 FIFO
->FreeSpace
= FIFO_FreeSpace
;
507 FIFO
->Flush
= FIFO_Flush
;
508 FIFO
->Truncate
= FIFO_Truncate
;
509 FIFO
->Delete
= FIFO_Delete
;
510 FIFO
->GetRDex
= FIFO_GetRDex
;
511 FIFO
->GetWDex
= FIFO_GetWDex
;
514 FIFO
->ElementSize
= (UINT32
)ElementSize
;
515 FIFO
->NumElements
= (UINT32
)NumElements
;
517 FIFO
->WriteIndex
= 0;