diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-10-05 14:20:04 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-10-05 14:20:04 +0200 |
| commit | 6e467ace41a9c5b21b3013340127b341faa8754f (patch) | |
| tree | cfce847ab1a45f6aaffa44e4d5083aa7e4e6fad1 | |
| parent | 01438d77a5cfd21ab9e11afba9be9386731e61f9 (diff) | |
| download | kernel-6e467ace41a9c5b21b3013340127b341faa8754f.tar.xz kernel-6e467ace41a9c5b21b3013340127b341faa8754f.zip | |
kstd: ring_buffer: provide basic exception safety
| -rw-r--r-- | libs/kstd/kstd/ring_buffer.hpp | 59 |
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. |
