aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-10-05 14:20:04 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-10-05 14:20:04 +0200
commit6e467ace41a9c5b21b3013340127b341faa8754f (patch)
treecfce847ab1a45f6aaffa44e4d5083aa7e4e6fad1
parent01438d77a5cfd21ab9e11afba9be9386731e61f9 (diff)
downloadkernel-6e467ace41a9c5b21b3013340127b341faa8754f.tar.xz
kernel-6e467ace41a9c5b21b3013340127b341faa8754f.zip
kstd: ring_buffer: provide basic exception safety
-rw-r--r--libs/kstd/kstd/ring_buffer.hpp59
1 files changed, 39 insertions, 20 deletions
diff --git a/libs/kstd/kstd/ring_buffer.hpp b/libs/kstd/kstd/ring_buffer.hpp
index 8176b68b..48711cd3 100644
--- a/libs/kstd/kstd/ring_buffer.hpp
+++ b/libs/kstd/kstd/ring_buffer.hpp
@@ -3,6 +3,7 @@
#include <kstd/bits/basic_storage.hpp>
#include <kstd/os/error.hpp>
+#include <kstd/ranges.hpp>
#include <algorithm>
#include <compare>
@@ -378,16 +379,20 @@ namespace kstd
if (to_copy_assign < other.m_size)
{
- std::ranges::for_each(std::views::iota(to_copy_assign, other.m_size),
- [&](auto const i) { std::construct_at(element_at(i), other[i]); });
+ std::ranges::for_each(std::views::iota(to_copy_assign, other.m_size), [&](auto const i) {
+ std::construct_at(element_at(i), other[i]);
+ ++m_size;
+ });
}
else if (to_copy_assign < m_size)
{
- std::ranges::for_each(std::views::drop(*this, to_copy_assign),
- [](auto & element) { std::destroy_at(&element); });
+ std::ranges::for_each(std::views::iota(to_copy_assign, m_size) | std::views::reverse, [&](auto const i) {
+ auto * element = element_at(i);
+ --m_size;
+ std::destroy_at(element);
+ });
}
- m_size = other.m_size;
return *this;
}
@@ -404,26 +409,34 @@ namespace kstd
}
auto const to_move_assign = std::min(m_size, other.m_size);
- std::ranges::for_each(std::views::enumerate(std::views::take(other, to_move_assign)), [&](auto const & entry) {
- auto & [i, element] = entry;
- (*this)[i] = std::move(element);
- std::destroy_at(other.element_at(i));
+ std::ranges::for_each(std::views::iota(0uz, to_move_assign), [&](auto const i) {
+ (*this)[i] = std::move(other[0]);
+ auto * to_destroy = other.element_at(0);
+ other.m_read_index = (other.m_read_index + 1) % other.capacity();
+ --other.m_size;
+ std::destroy_at(to_destroy);
});
- if (to_move_assign < other.m_size)
+ if (other.m_size > 0)
{
- std::ranges::for_each(std::views::iota(to_move_assign, other.m_size), [&](auto const i) {
- std::construct_at(element_at(i), std::move(other[i]));
- std::destroy_at(other.element_at(i));
+ std::ranges::for_each(std::views::iota(0uz, other.m_size), [&](auto) {
+ std::construct_at(element_at(m_size), std::move(other[0]));
+ ++m_size;
+ auto * to_destroy = other.element_at(0);
+ other.m_read_index = (other.m_read_index + 1) % other.capacity();
+ --other.m_size;
+ std::destroy_at(to_destroy);
});
}
else if (to_move_assign < m_size)
{
- std::ranges::for_each(std::views::drop(*this, to_move_assign),
- [](auto & element) { std::destroy_at(&element); });
+ std::ranges::for_each(std::views::iota(to_move_assign, m_size) | std::views::reverse, [&](auto const i) {
+ auto * to_destroy = element_at(i);
+ --m_size;
+ std::destroy_at(to_destroy);
+ });
}
- m_size = std::exchange(other.m_size, 0);
return *this;
}
@@ -688,11 +701,16 @@ namespace kstd
//! @name Modifiers
//! @{
+ //! Clear all elements from this ring buffer.
constexpr auto clear() noexcept(std::is_nothrow_destructible_v<ValueType>) -> void
{
- std::ranges::for_each(std::views::reverse(*this), [](auto & element) { std::destroy_at(&element); });
- m_size = 0;
- m_read_index = 0;
+ if constexpr (Capacity > 0)
+ {
+ while (!empty())
+ {
+ pop_front();
+ }
+ }
}
//! Construct an element at the end of this ring buffer.
@@ -796,9 +814,10 @@ namespace kstd
os::panic("[KSTD] Tried to pop an element from an empty ring_buffer!");
}
- std::destroy_at(element_at(0));
+ auto to_destroy = element_at(0);
m_read_index = (m_read_index + 1) % capacity();
--m_size;
+ std::destroy_at(to_destroy);
}
//! Try to remove the first element in the buffer.