User Tools

Site Tools


k7:k7.3:k7.3.6:start

7.3.6 Class Circular (gb. data)

The class Circular presents a circular buffer as a memory area with a fixed size. If the buffer is full, the oldest elements in the buffer are only overwritten with new elements if the Circular. Overwrite = True property has been set. All elements of a circular object are of type Variant.

A circular has a constant memory requirement because it is an internal array with a fixed number of elements. A circular with e. g. eight elements will never consume more memory than 8 * SizeOf (gb. Variant).

In addition, a circular has a reading and writing pointer. These two properties (. reader and. writer) are separated to distinguish between data producer (the Write () method) and data consumer (Read () method) who can manipulate the same object asynchronously.

If the read pointer reaches the write pointer, there are no further unread elements and the circular is called “empty”. If, on the other hand, the read pointer reaches the read pointer, there is no more space in the circular for new elements and it is declared “full”.

7.3.6.1 Properties

The characteristics of the Circular:

Property Data typeDescription
.SizeIntegerRead or set the number of elements (–> method Resize ())
.IsEmptyBoolean (ReadOnly)True, if there are no elements in the circular, otherwise false
.IsFullBoolean (ReadOnly)True, if all seats in the circular are occupied, otherwise false
.OverwriteBooleanIf true, the oldest element will be overwritten when the circular is full, otherwise any further attempts to write to a full circular will fail (without producing an error)
.ReaderIntegerIndex of the read pointer
.WriterIntegerIndex of the Write pointer

Table 7.3.6.6.1.1: Properties of the Circular class

7.3.6.2 Methods of a circular object

MethodDescription
Clear ()Remove all elements from buffer
Read ()Read the oldest element or zero, if the circular is empty
Peek ()Read () without moving the read pointer further
Write (vElement) Write a new element. When the circular is full, the effect of the method depends on the value of the Overwrite property.
Reset ()Reset read and write pointer to index 0
Resize (iSize) Change the size of the circular

Table 7.3.6.2.1: Methods of the class Circular

Attention: The method Circular. Resize () leaves the relation of the properties Reader and Writer in an undefined state.

Therefore, it is strongly recommended to let each Resize () be followed by a Reset () to avoid accidental crashes due to false assumptions. Alternatively, both pointers can have the same value when Resize () is called. In this case, both hands also have the same value after resizing the circular.

7.3.6.3 Project for using the class Circular

By using a circular buffer, the maximum memory usage of an application can be reduced to a constant size, since old data is automatically overwritten with new data. This mechanism is used for program logs, as they are of particular interest when a program produces errors. The log information written immediately before the program crash can refer to the part of the program that generated the error. This typical application program log with circular buffers is demonstrated in the offered project.

To keep the solution open, a client-server system is used, which implements a network-compatible system log service that maintains its own log for each connected program (client).

  • Only the server creates a log for each (client) program and maintains the contents of the individual logs.
  • Each log uses the class Circular. You can specify how many elements such a circular buffer has.
  • The number of elements determines the size of the circular buffer.
  • The log can only be accessed if the (client) program terminated or crashed regularly.

The following description assumes that 2 (client) programs are connected to the server:

ServerCircular

Figure 7.3.6.3.1: Two active (client) programs are logged on to the server

The server assigns an ID to the first (client) program and creates a (temporary) log file:

ClientCircular

Figure 7.3.6.3.3.2: (client) program 0

You can now work with program 0 by selecting different expressions from the combo box or by entering your own expressions there. You can catch an error or provoke a program crash. In this case the program 0 is terminated.

In the next figure 7.3.6.3.3.3, you can see that a corresponding message has been generated in the client overview. It also indicates that you cannot access the log of the 2nd active (client) program - access is denied!

Server2

Figure 7.3.6.3.3.3: Server with entries and warnings

Server3

Figure 7.3.6.3.4: Viewing the contents of the Client 0 log

The contents of a log are only displayed if you click on the entry “Terminated Client #…”.

Since each log exists only at runtime of the server, you can save the log for each (client) program and store it freely.


Supplement:
The new component gb. logging from Sebastian Kulesz provides a flexible API for logging and tracing events while the program is running.

Download

7.3.6 Klasse Circular (gb.data)

Die Klasse Circular präsentiert einen zirkulären Puffer als Speicherbereich mit fester Größe. Wenn der Puffer voll ist, werden die ältesten Elemente im Puffer mit neuen Elementen nur dann überschrieben, wenn die Eigenschaft Circular.Overwrite = True gesetzt wurde. Alle Elemente eines Circular-Objekts sind vom Typ Variant.

Ein Circular hat einen konstanten Speicherbedarf, denn es ist intern ein Array mit fixer Anzahl von Elementen. Ein Circular mit beispielsweise acht Elementen wird niemals mehr Speicher verbrauchen als 8 * SizeOf(gb.Variant).

Zusätzlich verfügt ein Circular über einen Lese- und Schreib-Zeiger. Diese beiden Eigenschaften (.Reader und .Writer) sind getrennt, um eine Unterscheidung von Daten-Produzent (die Write()-Methode) und Daten-Konsument (Read()-Methode) zu gewährleisten, welche asynchron dasselbe Objekt manipulieren können.

Erreicht der Lese-Zeiger den Schreib-Zeiger, so existieren keine weiteren ungelesenen Elemente und der Circular wird als “leer” bezeichnet. Erreicht hingegen der Schreib-Zeiger den Lese-Zeiger, so ist kein Platz mehr im Circular für neue Elemente und er wird als “voll” deklariert.

7.3.6.1 Eigenschaften

Die Eigenschaften des Circular:

Eigenschaft DatentypBeschreibung
.SizeIntegerLesen oder Setzen der Anzahl der Elemente (→ Methode Resize())
.IsEmptyBoolean (ReadOnly)Wahr, wenn keine Elemente im Circular sind, sonst falsch
.IsFullBoolean (ReadOnly)Wahr, wenn alle Plätze im Circular besetzt sind, sonst falsch
.OverwriteBooleanWenn wahr, so wird das älteste Element überschrieben, wenn der Circular voll ist, ansonsten schlägt jeder weitere Schreibversuch in einen vollen Circular fehl (ohne einen Fehler zu produzieren).
.Reader IntegerIndex des Lese-Zeigers
.WriterIntegerIndex des Schreib-Zeigers

Tabelle 7.3.6.1.1: Eigenschaften der Klasse Circular

7.3.6.2 Methoden eines Circular-Objektes

MethodeBeschreibung
Clear()Entfernen aller Elemente aus dem Puffer
Read()Lesen des ältesten Elements oder Null, wenn der Circular leer ist
Peek()Read() ohne den Lese-Zeiger weiter zu rücken
Write(vElement) Schreiben eines neuen Elements. Wenn der Circular voll ist, hängt die Auswirkung der Methode vom Wert der Eigenschaft Overwrite ab.
Reset()Lese- und Schreib-Zeiger auf Index 0 zurücksetzen
Resize(iSize) Ändern der Größe des Circular

Tabelle 7.3.6.2.1: Methoden der Klasse Circular

Achtung: Die Methode Circular.Resize() belässt die Relation der Eigenschaften Reader und Writer in einem undefinierten Zustand.

Es wird deshalb dringend empfohlen, jedem Resize() ein Reset() folgen zu lassen, um zufällige Abstürze infolge falscher Annahmen zu vermeiden. Alternativ können auch beide Zeiger denselben Wert besitzen, wenn Resize() aufgerufen wird. In diesem Fall haben beide Zeiger nach der Größenänderung des Circulars ebenfalls denselben Wert.

7.3.6.3 Projekt zum Einsatz der Klasse Circular

Durch den Einsatz eines zirkulären Puffers lässt sich die maximale Speichernutzung einer Anwendung auf eine konstante Größe reduzieren, da alte Daten automatisch mit neuen überschrieben werden. Dieser Mechanismus kommt bei Programm-Logs zum Einsatz, da diese vornehmlich dann interessant werden, wenn ein Programm Fehler produziert. Die unmittelbar vor dem Absturz des Programms geschriebenen Log-Informationen können auf den Programmteil verweisen, der den Fehler erzeugte. Diese typische Anwendung Programm-Log mit zirkulären Puffern wird im angebotenen Projekt demonstriert.

Um die Lösung offen zu halten wird ein Client-Server-System verwendet, das einen netzwerkfähigen System-Log-Service implementiert, der für jedes angeschlossene Programm (Client) ein eigenes Log führt.

  • Nur der Server legt für jedes (Client-)Programm ein Log an und pflegt den Inhalt der einzelnen Logs.
  • Jedes Log setzt die Klasse Circular ein. Es kann festgelegt werden, wie viele Elemente ein solcher zirkulärer Puffer hat.
  • Die Anzahl der Elemente bestimmt die Größe des zirkulären Puffers.
  • Auf das Log kann nur zugegriffen werden, wenn das (Client-)Programm regulär beendet wurde oder abgestürzt ist.

In der folgenden Beschreibung wird davon ausgegangen, dass 2 (Client-)Programme mit dem Server verbunden sind:

ServerCircular

Abbildung 7.3.6.3.1: Zwei aktive (Client-)Programme sind am Server angemeldet

Der Server weist dem ersten (Client-)Programm eine ID zu und legt eine (temporäre) Log-Datei an:

ClientCircular

Abbildung 7.3.6.3.2: (Client-)Programm 0

Sie können nun mit dem Programm 0 arbeiten, indem Sie unterschiedliche Ausdrücke aus der ComboBox auswählen oder eigene Ausdrücke dort eintragen. Sie können einen Fehler abfangen oder einen Programm-Absturz provozieren. In diesem Fehler-Fall wird das Programm 0 beendet.

In der nächsten Abbildung 7.3.6.3.3 erkennen Sie, dass in der Client-Übersicht eine entsprechende Meldung generiert wurde. Außerdem wird angezeigt, dass Sie nicht auf das Log des 2. aktiven (Client-)Programms zugreifen können – der Zugriff wird verweigert!

Server2

Abbildung 7.3.6.3.3: Server mit Eintragungen und Warnungen

Server3

Abbildung 7.3.6.3.4: Ansicht des Inhalts des Logs von Client 0

Der Inhalt eines Logs wird nur dann angezeigt, wenn man auf den Eintrag “Beendeter Client #..” klickt.

Da jedes Log nur zur Laufzeit des Servers existiert, kann man das Log für jedes (Client-)Programm sichern und frei abspeichern.


Ergänzung:
Die neue Komponente gb.logging vom Sebastian Kulesz stellt eine flexible API für das Logging und Nachverfolgen von Ereignissen bereit, während das Programm läuft.

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k7/k7.3/k7.3.6/start.txt · Last modified: 02.07.2018 (external edit)

Page Tools