Por favor, antes de enviar una solicitud de soporte, lea cuidadosamente este readme y verifique si ya existe una respuesta entre las preguntas respondidas anteriormente: No abuse del rastreador de problemas de GitHub.
La biblioteca en sí tiene un consumo de memoria implícito de aproximadamente 0.5kb : 580 bytes (máximo) de código y 8 bytes de memoria, según mis cálculos. Eso no considera el espacio utilizado para almacenar los artículos ellos mismos, obviamente.
Al declarar su búfer, debe especificar el tipo de datos que debe manejar y la capacidad del búfer: esos dos parámetros influirán en la memoria consumida por el búfer.
# 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
Tenga en cuenta : el uso de la memoria informado anteriormente incluye la memoria del programa utilizada por el código de la biblioteca, la memoria del montón es mucho menor y es comparable a una matriz del mismo tamaño y tipo de búfer.
Comencemos a aclarar las cosas: la biblioteca no admite insertar datos en el medio del búfer. Puede agregar datos al búfer antes del primer elemento a través de una operación unshift()
o después del último elemento a través de una operación push()
. Puede seguir agregando datos más allá de la capacidad máxima del búfer, pero perderá la información menos significativa:
unshift()
se suma a la cabeza , agrega más allá de la capacidad hace que el elemento en la cola se sobrescriba y se pierdapush()
se suma a la cola , más allá de más allá de la capacidad hace que el elemento en la cabeza se sobrescriba y se pierda Tanto unshift()
como push()
devuelve true
si la adición no causó ninguna pérdida de información, false
si se produjo una sobrescritura:
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
De manera similar a la adición de datos, la recuperación de datos se puede realizar en la cola a través de una operación pop()
o desde la cabeza a través de una operación shift()
: ambos hacen que el elemento se lea se elimine del búfer.
La lectura de datos más allá del tamaño real del búfer tiene un comportamiento indefinido y es responsabilidad del usuario de evitar tales violaciones de límites utilizando las operaciones adicionales enumeradas en la siguiente sección. La biblioteca se comportará de manera diferente dependiendo del tipo de datos y el método de asignación, pero puede asumir de manera segura que su programa se bloqueará si no observa sus pasos.
Las operaciones de lectura no destructivas también están disponibles:
first()
Devuelve el elemento en la cabezalast()
Devuelve el elemento en la cola[]
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()
devuelve true
solo si no se almacenan datos en el búferisFull()
Devuelve true
si no se pueden agregar datos al búfer sin causar sobrescritura/pérdida de datossize()
Devuelve el número de elementos actualmente almacenados actualmente en el búfer; Debe usarse junto con el operador []
para evitar violaciones de límites: el índice del primer elemento es siempre 0
(si el búfer no está vacío), el último índice de elementos siempre es size() - 1
available()
Devuelve el número de elementos que se pueden agregar antes de saturar el búfercapacity()
Devuelve el número de elementos que el búfer puede almacenar, para la integridad solo, ya que está definida por el usuario y nunca cambia de eliminación de 1.3.0
reemplazado por la capacity
variable de solo lectura de lecturaclear()
restablece todo el amortiguador a su estado inicial (sin embargo, preste atención, si tenía objetos asignados dinámicamente en su búfer, la memoria utilizada por dicho objeto no se libera: iterar sobre el contenido del búfer y liberar objetos en consecuencia a su método de asignación)copyToArray(array)
copia el contenido del búfer a una array
de matriz estándar. La matriz debe ser lo suficientemente grande como para contener todos los elementos actualmente en el búfer.copyToArray(conversionFn, array)
copia el contenido del búfer a una array
de matriz estándar que ejecuta una función en cada elemento, generalmente una conversión de tipo. La matriz debe ser lo suficientemente grande como para contener todos los elementos actualmente en el búfer. A partir de la versión 1.3.0
la biblioteca es capaz de detectar automáticamente qué tipo de datos debe usarse para el índice en función de la capacidad del búfer:
65535
, entonces su índice será un unsigned long
unsigned int
para amortiguadores con una capacidad declarada superior a 255
byte
va a ser suficienteAdemás, puede mezclar los mismos búferes de código con un índice pequeño y buffers con índice normal: anteriormente esto no era posible.
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)
Para obtener la máxima ventaja de la optimización anterior, cada vez que necesita consultar el índice de búfer, debe usar el tipo más apropiado: esto se puede lograr fácilmente utilizando el especificador decltype
, como en el siguiente ejemplo:
// 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 ();
}
Si lo prefiere, puede alias el tipo de índice y consulte dicho alias:
using index_t = decltype(buffer):: index_t ;
for ( index_t i = 0 ; i < buffer.size(); i++) {
avg += buffer[i] / buffer. size ();
}
Lo siguiente se aplica a versiones antes de 1.3.0
solamente.
Por defecto, la biblioteca utiliza índices unsigned int
, lo que permite un máximo de 65535
elementos, pero rara vez necesitará una tienda tan grande.
Puede cambiar los índices de la biblioteca al tipo byte
que define la macro CIRCULAR_BUFFER_XS
antes de la directiva #include
: esto reduce la memoria utilizada por la biblioteca en sí solo por 36
bytes, pero le permite exprimir mucho más cada vez que realiza un acceso indexado, si Usted hace cualquiera, utilizando el tipo de datos más pequeño.
# 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]);
}
}
Tenga en cuenta : este interruptor macro obliga al búfer a usar un tipo de datos de 8 bits como índice interno, ya que todos sus búferes se limitarán a una capacidad máxima de 255
.
La biblioteca ayuda a trabajar con interrupciones que definen el interruptor de macro CIRCULAR_BUFFER_INT_SAFE
, que introduce el modificador volatile
de la variable count
, lo que hace que toda la biblioteca sea más amigable para las interrupciones al precio de deshabilitar algunas optimizaciones del compilador. La declaración #define
debe colocarse en algún lugar antes de la declaración #include
:
# 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 );
}
Tenga en cuenta que esto no hace que la interrupción de la biblioteca sea segura , pero ayuda a su uso en firmwares impulsados por interrupciones.
Hay múltiples ejemplos disponibles en la carpeta de examples
de la biblioteca:
copyToArray()
. Si usa esta biblioteca para almacenar objetos asignados dinámicamente, abstenerse de usar el método clear()
, ya que no realizará la Memoria de desacuerdo: necesita iterar sobre el contenido de su búfer y liberar la memoria de acuerdo con el método de asignación utilizado, ya sea a través de delete
(si Usted usó new
) o free
(en caso de malloc
):
while (!buffer.isEmpty()) {
// pick the correct one
delete buffer. pop ();
free (buffer. pop ());
}
Lo mismo se aplica para las operaciones pop()
y shift()
ya que cualquier objeto asignado dinámicamente solo se separa del búfer, pero la memoria que usa no se libera automáticamente (consulte el ejemplo de Object.ino)
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)
y copyToArray(array, convertFn)
.h
a .hpp
shift()
y pop()
para estropear el búfer[]
abort()
es específico de AVRLa mayoría de las principales mejoras a continuación han sido aportadas por Erlkoenig90: ¡Gracias Niklas!
capacity()
a favor de la capacity
de atributo de instancia constanteEventLogging
e Interrupts
CIRCULAT_BUFFER_XS
a favor de la identificación de tipo de índice automáticoUINT32_MAX
)CIRCULAR_BUFFER_INT_SAFE
relacionado con la interrupciónmemset
al bordeclear()
fija ()pop()
fijapop()
y shift()
fijadascapacity()
debug()
agregada, deshabilitada por preprocesador de forma predeterminada