A ringbuffer in PB
Posted: Sat Sep 08, 2012 4:32 pm
Hi,
I needed a ringbuffer to solve my ReadNetworkData() problem.
So here it is (save it as RingBuffer.pbi):
To use it:
1. Define RB.RingBuffer_Structure
2. RingBuffer_Init(@RB, Your_wanted_size)
Use RingBuffer_Put() and RingBuffer_Get()
To look if something is available to read: RingBuffer_BytesToRead()
n. RingBuffer_Free(@RB)
With the optional parameter Mode = #RingBuffer_Peekmode of RingBuffer_Get(),
you can get data without removing them from the buffer.
(To test a received byte, before you read the whole packet, for example)
Have fun
Bernd
I needed a ringbuffer to solve my ReadNetworkData() problem.
So here it is (save it as RingBuffer.pbi):
Code: Select all
;
; RingBuffer implementation
;
; by infratec
Enumeration
#RingBuffer_Getmode
#RingBuffer_Peekmode
EndEnumeration
Structure RingBuffer_Structure
*RingBuffer
Size.i
ReadPtr.i
WritePtr.i
EndStructure
Procedure.i RingBuffer_Init(*RB.RingBuffer_Structure, Size.i)
*RB\RingBuffer = AllocateMemory(Size)
If *RB\RingBuffer
*RB\Size = Size
*RB\ReadPtr = 0
*RB\WritePtr = 0
Else
*RB\Size = 0
EndIf
ProcedureReturn *RB\Size
EndProcedure
Procedure.i RingBuffer_BytesToRead(*RB.RingBuffer_Structure)
Protected Result.i
If *RB\WritePtr = *RB\ReadPtr
Result = 0
ElseIf *RB\WritePtr > *RB\ReadPtr
Result = *RB\WritePtr - *RB\ReadPtr
Else
Result = *RB\Size - (*RB\ReadPtr - *RB\WritePtr)
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i RingBuffer_Put(*RB.RingBuffer_Structure, *Src, Bytes.i)
Protected Result.i, Help.i
Result = #False
If *RB\Size - RingBuffer_BytesToRead(*RB) >= Bytes
If *RB\WritePtr + Bytes <= *RB\Size
CopyMemory(*Src, *RB\RingBuffer + *RB\WritePtr, Bytes)
*RB\WritePtr + Bytes
Else
Help = *RB\Size - *RB\WritePtr
CopyMemory(*Src, *RB\RingBuffer + *RB\WritePtr, Help)
CopyMemory(*Src + Help, *RB\RingBuffer, Bytes - Help)
*RB\WritePtr = Bytes - Help
EndIf
Result = #True
EndIf
ProcedureReturn Result
EndProcedure
Procedure.i RingBuffer_Get(*RB.RingBuffer_Structure, *Dst, Bytes.i, Mode.i = #RingBuffer_Getmode)
Protected AvailableBytes.i, Part.i
AvailableBytes = RingBuffer_BytesToRead(*RB)
If AvailableBytes > 0
If AvailableBytes < Bytes : Bytes = AvailableBytes : EndIf
If *RB\Size - *RB\ReadPtr >= Bytes
CopyMemory(*RB\RingBuffer + *RB\ReadPtr, *Dst, Bytes)
If Mode = #RingBuffer_Getmode : *RB\ReadPtr + Bytes : EndIf
Else
Part = *RB\Size - *RB\ReadPtr
CopyMemory(*RB\RingBuffer + *RB\ReadPtr, *Dst, Part)
CopyMemory(*RB\RingBuffer, *Dst + Part, Bytes - Part)
If Mode = #RingBuffer_Getmode : *RB\ReadPtr = Bytes - Part : EndIf
EndIf
Else
Bytes = 0
EndIf
ProcedureReturn Bytes
EndProcedure
Procedure RingBuffer_Clear(*RB.RingBuffer_Structure)
*RB\ReadPtr = 0
*RB\WritePtr = 0
EndProcedure
Procedure RingBuffer_Free(*RB.RingBuffer_Structure)
FreeMemory(*RB\RingBuffer)
*RB\Size = 0
*RB\ReadPtr = 0
*RB\WritePtr = 0
EndProcedure
1. Define RB.RingBuffer_Structure
2. RingBuffer_Init(@RB, Your_wanted_size)
Use RingBuffer_Put() and RingBuffer_Get()
To look if something is available to read: RingBuffer_BytesToRead()
n. RingBuffer_Free(@RB)
With the optional parameter Mode = #RingBuffer_Peekmode of RingBuffer_Get(),
you can get data without removing them from the buffer.
(To test a received byte, before you read the whole packet, for example)
Have fun

Bernd