Vor dem Einreichen einer Support -Anfrage lesen Sie diese Readme sorgfältig und überprüfen Sie, ob eine Antwort bereits unter zuvor beantworteten Fragen vorhanden ist: Missbrauch nicht den GitHub -Ausgaber -Tracker.
Die Bibliothek selbst hat einen impliziten Speicherverbrauch von ca. 0,5 KB : 580 Bytes (max) Code und 8 Speicherbytes gemäß meinen Berechnungen. Dies berücksichtigt nicht den Raum, mit dem die Gegenstände selbst selbst gespeichert werden.
Wenn Sie Ihren Puffer deklarieren, sollten Sie den Datentyp und die Pufferkapazität angeben: Diese beiden Parameter beeinflussen den vom Puffer verbrauchten Speicher.
# include < CircularBuffer.hpp >
CircularBuffer<byte, 100 > bytes; // uses 538 bytes
CircularBuffer< int , 100 > ints; // uses 638 bytes
CircularBuffer< long , 100 > longs; // uses 838 bytes
CircularBuffer< float , 100 > floats; // uses 988 bytes
CircularBuffer< double , 100 > doubles; // uses 988 bytes
CircularBuffer< char , 100 > chars; // uses 538 bytes
CircularBuffer< void *, 100 > pointers; // uses 638 bytes
Bitte beachten Sie : Die oben angegebene Speicherverwendung enthält den vom Bibliothekscode verwendeten Programmspeicher. Der Heap -Speicher ist viel geringer und ist mit einem Array mit derselben Größe und einem Typ des Puffers vergleichbar.
Lassen Sie uns die Dinge klarstellen: Die Bibliothek unterstützt das Einfügen von Daten in der Mitte des Puffers nicht. Sie können den Puffer entweder vor dem ersten Element über einen unshift()
oder nach dem letzten Element über eine push()
-Operation hinzufügen. Sie können weiterhin Daten über die maximale Kapazität von Puffer hinzufügen, aber Sie verlieren die am wenigsten signifikanten Informationen:
unshift()
den Kopf ergänzt, wird das Hinzufügen von Überkapazität dazu führt, dass das Element am Schwanz überschrieben und verloren gehtpush()
Sowohl unshift()
als auch push()
geben true
zurück, wenn die Zugabe keinen Informationsverlust verursachte, false
wenn ein Überschreiben aufgetreten ist:
CircularBuffer< int , 5 > buffer; // buffer capacity is 5
// all of the following return true
buffer.unshift( 1 ); // [1]
buffer.unshift( 2 ); // [2,1]
buffer.unshift( 3 ); // [3,2,1]
buffer.push( 0 ); // [3,2,1,0]
buffer.push( 5 ); // [3,2,1,0,5]
// buffer is now at full capacity, from now on any addition returns false
buffer.unshift( 2 ); // [2,3,2,1,0] returns false
buffer.unshift( 10 ); // [10,2,3,2,1] returns false
buffer.push(- 5 ); // [2,3,2,1,-5] returns false
Ähnlich wie bei der Datenerfassung kann das Datenab Abrufen am Schwanz über einen pop()
-Operationsvorgang oder über einen Kopf über einen shift()
-Operation durchgeführt werden: Beide führen dazu, dass das Element gelesen wird, das aus dem Puffer entfernt wird.
Das Lesen von Daten über die tatsächliche Puffergröße hinaus ist ein undefiniertes Verhalten und ist die Verantwortung des Benutzers, solche Grenzverstöße anhand der im nächsten Abschnitt aufgeführten zusätzlichen Vorgänge zu verhindern. Die Bibliothek verhält sich je nach Datentyp und Allokationsmethode unterschiedlich. Sie können jedoch sicher davon ausgehen, dass Ihr Programm abstürzt, wenn Sie Ihre Schritte nicht ansehen.
Es sind auch nicht zerstörerische Lesevorgänge verfügbar:
first()
gibt das Element am Kopf zurücklast()
gibt das Element am Schwanz zurück[]
Operator lesen können CircularBuffer< char , 50 > buffer; // ['a','b','c','d','e','f','g']
buffer.first(); // ['a','b','c','d','e','f','g'] returns 'a'
buffer.last(); // ['a','b','c','d','e','f','g'] returns 'g'
buffer.pop(); // ['a','b','c','d','e','f'] returns 'g'
buffer.pop(); // ['a','b','c','d','e'] returns 'f'
buffer.shift(); // ['b','c','d','e'] returns 'a'
buffer.shift(); // ['c','d','e'] returns 'b'
buffer[ 0 ]; // ['c','d','e'] returns 'c'
buffer[ 1 ]; // ['c','d','e'] returns 'd'
buffer[ 2 ]; // ['c','d','e'] returns 'e'
buffer[ 10 ]; // ['c','d','e'] returned value is unpredictable
buffer[ 15 ]; // ['c','d','e'] returned value is unpredictable
isEmpty()
gibt nur dann true
zurück, wenn keine Daten im Puffer gespeichert sindisFull()
gibt true
zurück, wenn keine Daten zum Puffer hinzugefügt werden können, ohne Überschreibungen/Datenverluste zu verursachensize()
gibt die Anzahl der derzeit im Puffer gespeicherten Elemente zurück. Es sollte in Verbindung mit dem []
Operator verwendet werden size() - 1
um Grenzverstöße 0
vermeidenavailable()
gibt die Anzahl der Elemente zurück, die vor dem Sättigung des Puffers hinzugefügt werden könnencapacity()
gibt die Anzahl der Elemente zurück, die der Puffer speichern kann, nur für die Vollständigkeit, da er benutzerdefiniert ist und sich nie von 1.3.0
ändern wird, die durch die capacity
der schreibgeschützten Mitglieder ersetzt werdenclear()
setzt den gesamten Puffer in seinen Ausgangszustand zurück (achten Sie jedoch auf, wenn Sie dynamisch Objekte in Ihrem Puffer zugeteilt haben, wird der von einem solchen Objekt verwendete Speicher nicht freigegeben: Iterieren Sie den Puffergehalt und lassen Sie Objekte entsprechend der Zuordnungsmethode frei.copyToArray(array)
kopiert den Inhalt des Puffers in ein Standard -Array array
. Das Array muss groß genug sein, um alle Elemente im Puffer zu halten.copyToArray(conversionFn, array)
kopiert den Inhalt des Puffers in ein Standard -Array array
das eine Funktion für jedes Element ausführt, normalerweise eine Typumwandlung. Das Array muss groß genug sein, um alle Elemente im Puffer zu halten. Ab Version 1.3.0
kann die Bibliothek automatisch erkennen, welcher Datentyp für den Index basierend auf der Pufferkapazität verwendet werden sollte:
65535
deklarieren, wird Ihr Index ein unsigned long
seinunsigned int
für Puffer mit einer deklarierten Kapazität von mehr als 255
byte
ausreichenDarüber hinaus können Sie die gleichen Codepuffer mit kleinem Index und Puffer mit normalem Index mischen: Zuvor war dies nicht möglich.
CircularBuffer< char , 100 > optimizedBuffer; // reduced memory footprint, index type is uint8_t (a.k.a. byte)
CircularBuffer< long , 500 > normalBuffer; // standard memory footprint, index type is unit16_t (a.k.a. unsigned int)
CircularBuffer< int , 66000 > hugeBuffer; // extended memory footprint, index type is unit32_t (a.k.a. unsigned long)
Um den maximalen Vorteil der oben genannten Optimierung zu erhalten, sollten Sie sich jederzeit auf den Pufferindex beziehen, den Sie den am besten geeigneten Typ verwenden müssen: Dies kann einfach mit dem decltype
-Spezifizierer wie im folgenden Beispiel erreicht werden:
// the iterator variable i is of the correct type, even if
// we don't know what's the buffer declared capacity
for (decltype(buffer):: index_t i = 0 ; i < buffer.size(); i++) {
avg += buffer[i] / buffer. size ();
}
Wenn Sie es vorziehen, können Sie den Indextyp alias und verweisen auf einen solchen Alias:
using index_t = decltype(buffer):: index_t ;
for ( index_t i = 0 ; i < buffer.size(); i++) {
avg += buffer[i] / buffer. size ();
}
Das Folgende gilt nur für Versionen vor 1.3.0
.
Standardmäßig verwendet die Bibliothek unsigned int
-Indizes, sodass maximal 65535
Elemente ermöglicht werden. Sie benötigen jedoch selten einen so riesigen Geschäft.
Sie können die Bibliotheksindizes auf byte
-Typ wechseln, die das Makro CIRCULAR_BUFFER_XS
vor der #include
-Anweisung definieren: Dies reduziert den von der Bibliothek selbst verwendeten Speicher um nur 36
Bytes, ermöglicht es Ihnen jedoch, möglicherweise viel mehr herauszudrücken, wenn Sie einen indizierten Zugriff ausführen, wenn Sie einen indizierten Zugriff ausführen, wenn Sie tun alle, indem Sie den kleineren Datentyp verwenden.
# define CIRCULAR_BUFFER_XS
# include < CircularBuffer.h >
CircularBuffer< short , 100 > buffer;
void setup () { }
void loop () {
// here i should be declared of type byte rather than unsigned int
// in order to maximize the effects of the optimization
for (byte i = 0 ; i < buffer. size () - 1 ; i++) {
Serial. print (buffer[i]);
}
}
Bitte beachten Sie : Dieser Makroschalter erzwingt den Puffer, um einen 8 -Bit -Datentyp als interner Index zu verwenden. Alle Ihre Puffer sind auf eine maximale Kapazität von 255
begrenzt.
Die Bibliothek hilft dabei, mit Interrupts zu arbeiten, um den Makroschalter CIRCULAR_BUFFER_INT_SAFE
zu definieren, der den volatile
Modifikator in die count
einführt, wodurch die gesamte Bibliothek zum Preis der Deaktivierung einiger Compiler-Optimierungen interruptfreundlicher wird. Die #define
-Erklärung muss irgendwo vor der #include
-Erklärung gestellt werden:
# define CIRCULAR_BUFFER_INT_SAFE
# include < CircularBuffer.h >
CircularBuffer< unsigned long , 10 > timings;
void count () {
timings. push ( millis ());
}
void setup () {
attachInterrupt ( digitalPinToInterrupt ( 2 ), count, RISING);
}
void loop () {
Serial. print ( " buffer size is " ); Serial. println (timings. size ());
delay ( 250 );
}
Bitte beachten Sie, dass dies die Bibliothek nicht sicher unterbricht, aber sie hilft der Verwendung in Interrupt -angetriebenen Firmawares.
Mehrere Beispiele sind im examples
-Ordner der Bibliothek verfügbar:
copyToArray()
. Wenn Sie diese Bibliothek verwenden, um dynamisch delete
Objekte zu speichern, verwenden Sie die Methode clear()
, da dies keine Speicherverwalter ausführt Sie hatten new
oder free
verwendet (im Fall von malloc
):
while (!buffer.isEmpty()) {
// pick the correct one
delete buffer. pop ();
free (buffer. pop ());
}
Gleiches gilt für die Operationen pop()
und shift()
da jedes dynamisch zugewiesene Objekt nur vom Puffer abgelöst wird , aber der von ihm verwendete Speicher ist nicht automatisch freigegeben (siehe Objekt.ino -Beispiel)
Record* record = new Record(millis(), sample); // a dynamically allocated object
buffer.push(record);
// somewhere else
if (!buffer.isEmpty()) {
Record* current = buffer. pop ();
Serial. println (current. value ());
delete current; // if you don't do this the object memory is lost!!!
}
copyToArray(array)
und copyToArray(array, convertFn)
.h
-Header -Erweiterung auf .hpp
shift()
und pop()
Operationen missbrauchen, um den Puffer durcheinander zu bringen[]
Operator aus dem Grenzzugriff verhindernabort()
ist avrspezifischDie meisten der wichtigsten Verbesserungen unten wurden von Erlkoenig90 beigetragen: Danke Niklas!
capacity()
zugunsten der konstanten capacity
EventLogging
und Interrupts
hinzuCIRCULAT_BUFFER_XS
zugunsten der automatischen Identifizierung des Indextyps gelöschtUINT32_MAX
ansteigen)CIRCULAR_BUFFER_INT_SAFE
hinzugefügtmemset
fallen gelassenclear()
Funktionpop()
Funktionpop()
und shift()
Implementierungencapacity()
-Funktion hinzugefügtdebug()
-Funktion hinzugefügt, die standardmäßig vom Pre-Processor deaktiviert ist