The iterator expects that no elements are added or removed to the
circular buffer during the iteration. A possible solution to detect
such a programming error would be to add a generation number to
struct circularBuffer
which is incremented with every modification.
Then copy that generation number to struct circularBufferIterator
in circularBufferIteratorPrepare()
and verify it to be unchanged
in circularBufferIteratorNext()
. I would add such a check at least
if the program is compiled in DEBUG
mode.
It suffices to
It suffices to
The iterator expects that no elements are added or removed to the
circular buffer during the iteration. A possible solution to detect
such a programming error would be to add a generation number to
struct circularBuffer
which is incremented with every modification.
Then copy that generation number to struct circularBufferIterator
in circularBufferIteratorPrepare()
and verify it to be unchanged
in circularBufferIteratorNext()
. I would add such a check at least
if the program is compiled in DEBUG
mode.
It suffices to
There is an asymmetry in your APIs, as can for example be seen in
You can replace calloc()
by malloc()
if the initialization with
zero bytes is not needed.
(If you are planning to work with – implementation-defined – "over-aligned" types then
the required alignment must be passed as an additional parameter to
the creation function, and more work is necessary to ensure that
the address of the data
field is property aligned.)
It suffices to
#include <stddef.h> // max_align_t in source
in the implementation file "circularBuffer.c", it is not needed in the header file "circularBuffer.h".
There is an asymmetry in your APIs, for example in
You can replace calloc()
by malloc()
if the initialization with
zero bytes is not needed.
There is an asymmetry in your APIs, as can for example be seen in
You can replace calloc()
by malloc()
if the initialization with
zero bytes is not needed.
(If you are planning to work with – implementation-defined – "over-aligned" types then
the required alignment must be passed as an additional parameter to
the creation function, and more work is necessary to ensure that
the address of the data
field is property aligned.)
It suffices to
#include <stddef.h> // max_align_t in source
in the implementation file "circularBuffer.c", it is not needed in the header file "circularBuffer.h".
Your calculations of alignElementSize
seem unnecessary to me
(and causes to more memory to be allocated than necessary).
Here are some quotes of the C11 standard (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):
It is then not necessary to separate between alignElementSize
and originalElementSize
and the test and allocationbuffer creation simplifies to to
struct circularBuffer *circularBufferCreate(size_t capacity, size_t elementSize) {
if (elementSize == 0) {
return NULL;
}
if ((SIZE_MAX - sizeof(struct circularBuffer)) / elementSize < capacity) {
return NULL;
}
struct circularBuffer *buf = calloc(1, sizeof(struct circularBuffer) + elementSize * capacity);
if (!buf) {
return NULL;
}
buf->capacity = capacity;
buf->cardinality = 0;
buf->elementSize = elementSize;
buf->headOffset = 0;
buf->tailOffset = 0;
return buf;
}
You can replace calloc()
by malloc()
if the initialization with
zero bytes is not needed.
Your calculations of alignElementSize
seem unnecessary to me.
Here are some quotes of the C11 standard (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):
It is then not necessary to separate between alignElementSize
and originalElementSize
and the test and allocation simplifies to
if ((SIZE_MAX - sizeof(struct circularBuffer)) / elementSize < capacity) {
return NULL;
}
struct circularBuffer *buf = calloc(1, sizeof(struct circularBuffer) + elementSize * capacity);
Your calculations of alignElementSize
seem unnecessary to me
(and causes to more memory to be allocated than necessary).
Here are some quotes of the C11 standard (taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):
It is then not necessary to separate between alignElementSize
and originalElementSize
and the buffer creation simplifies to
struct circularBuffer *circularBufferCreate(size_t capacity, size_t elementSize) {
if (elementSize == 0) {
return NULL;
}
if ((SIZE_MAX - sizeof(struct circularBuffer)) / elementSize < capacity) {
return NULL;
}
struct circularBuffer *buf = calloc(1, sizeof(struct circularBuffer) + elementSize * capacity);
if (!buf) {
return NULL;
}
buf->capacity = capacity;
buf->cardinality = 0;
buf->elementSize = elementSize;
buf->headOffset = 0;
buf->tailOffset = 0;
return buf;
}
You can replace calloc()
by malloc()
if the initialization with
zero bytes is not needed.