VB.NET-Quellcode
- ''' <summary>
- ''' Ein ziemlich einfacher FIFO-Ring-Puffer der
- ''' als "generics" Klasse aufgebaut ist
- ''' VERMUTLICH threadsicher!
- ''' </summary>
- ''' <typeparam name="T"></typeparam>
- ''' <remarks></remarks>
- Public Class SimpleFIFOBuffer(Of T)
- Private Const INITIAL_CAPACITY As Integer = 10
- Private Elements(INITIAL_CAPACITY - 1) As T
- Private ElementLock As New Object
- Private PushIndex As Integer = 0
- Private PullIndex As Integer = -1 ' -1 = kein Element zum Lesen vorhanden
- ''' <summary>
- ''' Ermittelt die Anzahl der (gültigen) Elemente im Puffer
- ''' </summary>
- ''' <value></value>
- ''' <returns>Anzahl der Elemente</returns>
- ''' <remarks></remarks>
- Public ReadOnly Property Size() As Integer
- Get
- SyncLock (ElementLock)
- ' Die einfache Möglichkeit:
- If PullIndex = -1 Then Return 0
- ' Es gibt zwei weitere Möglichkeiten:
- ' ..-xx xxx+. Pull < Push => Size = Push - Pull
- ' xx+.. .-xxx Pull > Push => Size = Elementanzahl - Pull + Push
- If PullIndex < PushIndex Then Return PushIndex - PullIndex
- If PushIndex <= PullIndex Then Return Elements.Length - PullIndex + PushIndex
- End SyncLock
- End Get
- End Property
- ''' <summary>
- ''' Legt ein Element im Puffer ab. Falls der Puffer zu
- ''' klein ist, wird er vergrößert.
- ''' </summary>
- ''' <param name="arg"></param>
- ''' <remarks></remarks>
- Public Sub Push(ByVal arg As T)
- SyncLock (ElementLock)
- If PushIndex = PullIndex Then
- ' Array muss vergrößert werden
- ReDim Preserve Elements(Elements.Length + INITIAL_CAPACITY - 1)
- ' elemente umkopieren. Dazu "schneiden" wir das
- ' Array an der PullIndex Position auf und fügen neue elemente ein
- For i As Integer = Elements.Length - 1 To PullIndex + INITIAL_CAPACITY Step -1
- Elements(i) = Elements(i - INITIAL_CAPACITY)
- Next
- ' Elemente löschen, die eigentlich nicht gültig sind:
- For i As Integer = PullIndex To PullIndex + INITIAL_CAPACITY - 1
- Elements(i) = Nothing
- Next
- ' Leseposition um x Elemente nach "vorne" verschieben
- PullIndex += INITIAL_CAPACITY
- ElseIf PullIndex = -1 Then
- ' PullIndex war "ungültig", aber da wir ja jetzt einen Wert
- ' schreiben, könnten wir den ja auch wieder lesen
- PullIndex = PushIndex
- End If
- ' Element speichern und Schreibpointer um 1 erhöhen
- Elements(PushIndex) = arg
- PushIndex = (PushIndex + 1) Mod Elements.Length
- End SyncLock
- End Sub
- ''' <summary>
- ''' Liest einen Wert vom Puffer
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function Pull() As T
- SyncLock (ElementLock)
- ' natürlich nur wenn's Sinn macht ...
- If PullIndex = -1 Then Throw New Exception("Puffer ist leer!")
- ' Element zwischenspeichern und dann
- ' im Array löschen
- Dim tmp As T = Elements(PullIndex)
- Elements(PullIndex) = Nothing
- PullIndex = (PullIndex + 1) Mod Elements.Length
- If PullIndex = PushIndex Then
- ' Der Puffer wurde komplett geleert
- PullIndex = -1
- If Elements.Length > INITIAL_CAPACITY Then
- ' Wir setzen den Puffer auf die ursprüngliche
- ' Größe zurück
- ReDim Elements(INITIAL_CAPACITY - 1)
- End If
- End If
- Return tmp
- End SyncLock
- End Function
- End Class