Ring buffer: Use memcpy when reallocating trivially copyable types
This commit is contained in:
@@ -264,10 +264,14 @@ public:
|
|||||||
}
|
}
|
||||||
this->head = 0;
|
this->head = 0;
|
||||||
this->count = other.count;
|
this->count = other.count;
|
||||||
uint8_t *ptr = this->data.get();
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
for (const T &item : other) {
|
other.memcpy_to(this->data.get());
|
||||||
new (ptr) T(item);
|
} else {
|
||||||
ptr += sizeof(T);
|
uint8_t *ptr = this->data.get();
|
||||||
|
for (const T &item : other) {
|
||||||
|
new (ptr) T(item);
|
||||||
|
ptr += sizeof(T);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,15 +342,47 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint8_t *memcpy_to(uint8_t *target, uint32_t start_pos, uint32_t end_pos) const
|
||||||
|
{
|
||||||
|
if (start_pos == end_pos) return target;
|
||||||
|
|
||||||
|
const uint8_t *start_ptr = static_cast<const uint8_t *>(this->raw_ptr_at_pos(start_pos));
|
||||||
|
const uint8_t *end_ptr = static_cast<const uint8_t *>(this->raw_ptr_at_pos(end_pos));
|
||||||
|
if (end_ptr <= start_ptr) {
|
||||||
|
/* Copy in two chunks due to wrap */
|
||||||
|
|
||||||
|
const uint8_t *buffer_end = this->data.get() + (this->capacity() * sizeof(T));
|
||||||
|
memcpy(target, start_ptr, buffer_end - start_ptr);
|
||||||
|
target += buffer_end - start_ptr;
|
||||||
|
|
||||||
|
memcpy(target, this->data.get(), end_ptr - this->data.get());
|
||||||
|
target += end_ptr - this->data.get();
|
||||||
|
} else {
|
||||||
|
/* Copy in one chunk */
|
||||||
|
memcpy(target, start_ptr, end_ptr - start_ptr);
|
||||||
|
target += end_ptr - start_ptr;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *memcpy_to(uint8_t *target) const
|
||||||
|
{
|
||||||
|
return this->memcpy_to(target, this->head, this->head + this->count);
|
||||||
|
}
|
||||||
|
|
||||||
void reallocate(uint32_t new_cap)
|
void reallocate(uint32_t new_cap)
|
||||||
{
|
{
|
||||||
const uint32_t cap = round_up_size(new_cap);
|
const uint32_t cap = round_up_size(new_cap);
|
||||||
uint8_t *new_buf = MallocT<uint8_t>(cap * sizeof(T));
|
uint8_t *new_buf = MallocT<uint8_t>(cap * sizeof(T));
|
||||||
uint8_t *pos = new_buf;
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
for (T &item : *this) {
|
this->memcpy_to(new_buf);
|
||||||
new (pos) T(std::move(item));
|
} else {
|
||||||
item.~T();
|
uint8_t *pos = new_buf;
|
||||||
pos += sizeof(T);
|
for (T &item : *this) {
|
||||||
|
new (pos) T(std::move(item));
|
||||||
|
item.~T();
|
||||||
|
pos += sizeof(T);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->mask = cap - 1;
|
this->mask = cap - 1;
|
||||||
this->head = 0;
|
this->head = 0;
|
||||||
@@ -523,17 +559,22 @@ private:
|
|||||||
/* grow container */
|
/* grow container */
|
||||||
const uint32_t cap = round_up_size(this->count + num);
|
const uint32_t cap = round_up_size(this->count + num);
|
||||||
uint8_t *new_buf = MallocT<uint8_t>(cap * sizeof(T));
|
uint8_t *new_buf = MallocT<uint8_t>(cap * sizeof(T));
|
||||||
uint8_t *write_to = new_buf;
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||||
const uint32_t end = this->head + this->count;
|
uint8_t *insert_gap = this->memcpy_to(new_buf, this->head, pos);
|
||||||
for (uint32_t idx = this->head; idx != end; idx++) {
|
this->memcpy_to(insert_gap + (num * sizeof(T)), pos, this->head + this->count);
|
||||||
if (idx == pos) {
|
} else {
|
||||||
/* gap for inserted items */
|
uint8_t *write_to = new_buf;
|
||||||
write_to += num * sizeof(T);
|
const uint32_t end = this->head + this->count;
|
||||||
|
for (uint32_t idx = this->head; idx != end; idx++) {
|
||||||
|
if (idx == pos) {
|
||||||
|
/* gap for inserted items */
|
||||||
|
write_to += num * sizeof(T);
|
||||||
|
}
|
||||||
|
T &item = *this->ptr_at_pos(idx);
|
||||||
|
new (write_to) T(std::move(item));
|
||||||
|
item.~T();
|
||||||
|
write_to += sizeof(T);
|
||||||
}
|
}
|
||||||
T &item = *this->ptr_at_pos(idx);
|
|
||||||
new (write_to) T(std::move(item));
|
|
||||||
item.~T();
|
|
||||||
write_to += sizeof(T);
|
|
||||||
}
|
}
|
||||||
uint32_t res = pos - this->head;
|
uint32_t res = pos - this->head;
|
||||||
this->mask = cap - 1;
|
this->mask = cap - 1;
|
||||||
|
Reference in New Issue
Block a user