From a1a1e8a552812c53447d468c260dab8a8a6fb58e Mon Sep 17 00:00:00 2001 From: wvpm <24685035+wvpm@users.noreply.github.com> Date: Sun, 11 Jan 2026 21:51:06 +0100 Subject: [PATCH] Fix empty reusable maps in ThreadPool --- src/openvic-simulation/types/FixedVector.hpp | 24 ++++++++++++++----- .../types/IndexedFlatMap.hpp | 6 ++--- src/openvic-simulation/types/TypedSpan.hpp | 1 + src/openvic-simulation/utility/ThreadPool.cpp | 4 ++-- tests/src/types/FixedVector.cpp | 10 ++++---- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/openvic-simulation/types/FixedVector.hpp b/src/openvic-simulation/types/FixedVector.hpp index 9aae833fa..9f9a7070b 100644 --- a/src/openvic-simulation/types/FixedVector.hpp +++ b/src/openvic-simulation/types/FixedVector.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -33,19 +34,30 @@ namespace OpenVic::_detail { constexpr T const* data() const { return _data_start_ptr; } constexpr bool empty() const { return _size == 0; } + /** + * @brief Creates an uninitialised vector with fixed capacity + */ explicit FixedVector(const size_t capacity) : _max_size(capacity), _size(0), _allocator(), _data_start_ptr(allocator_traits::allocate(_allocator, capacity)) {} + FixedVector(const size_t size, T const& value_for_all_indices) + : _max_size(size), + _size(size), + _allocator(), + _data_start_ptr(allocator_traits::allocate(_allocator, size)) { + std::fill(_data_start_ptr, _data_start_ptr + size, value_for_all_indices); + } + //Generator (size_t i) -> U (where T is constructable from U) template // The generator must NOT return a tuple requires (!specialization_of>, std::tuple>) // The type must be constructible from the generator's single return value && std::constructible_from()(std::declval()))> - FixedVector(size_t size, GeneratorTemplateType&& generator) + FixedVector(const size_t size, GeneratorTemplateType&& generator) : _max_size(size), _size(size), _allocator(), @@ -74,7 +86,7 @@ namespace OpenVic::_detail { ) }; } - FixedVector(size_t size, GeneratorTemplateType&& generator) + FixedVector(const size_t size, GeneratorTemplateType&& generator) : _max_size(size), _size(size), _allocator(), @@ -125,12 +137,12 @@ namespace OpenVic::_detail { const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } - T& operator[](size_t index) { - assert(index < _size && "Index out of bounds."); + T& operator[](const size_t index) { + assert(index < _size); return _data_start_ptr[index]; } - const T& operator[](size_t index) const { - assert(index < _size && "Index out of bounds."); + const T& operator[](const size_t index) const { + assert(index < _size); return _data_start_ptr[index]; } diff --git a/src/openvic-simulation/types/IndexedFlatMap.hpp b/src/openvic-simulation/types/IndexedFlatMap.hpp index 1ea92be65..051defad2 100644 --- a/src/openvic-simulation/types/IndexedFlatMap.hpp +++ b/src/openvic-simulation/types/IndexedFlatMap.hpp @@ -269,7 +269,7 @@ namespace OpenVic { ) : keys(new_keys), min_index { new_keys.front().index }, max_index { new_keys.back().index }, - values(new_keys.size()) { + values { new_keys.size() } { static_assert(has_index); if (!validate_new_keys(new_keys)) { return; @@ -363,7 +363,7 @@ namespace OpenVic { ) : keys(new_keys), min_index { type_safe::get(new_keys.front().index) }, max_index { type_safe::get(new_keys.back().index) }, - values(new_keys.size()) { + values { new_keys.size() } { static_assert(has_index); if (!validate_new_keys(new_keys)) { return; @@ -428,7 +428,7 @@ namespace OpenVic { : keys(new_keys), min_index { type_safe::get(new_keys.front().index) }, max_index { type_safe::get(new_keys.back().index) }, - values(new_keys.size()) { + values { new_keys.size() } { static_assert(has_index); if (!validate_new_keys(new_keys)) { return; diff --git a/src/openvic-simulation/types/TypedSpan.hpp b/src/openvic-simulation/types/TypedSpan.hpp index f82fc734f..5e58fbdac 100644 --- a/src/openvic-simulation/types/TypedSpan.hpp +++ b/src/openvic-simulation/types/TypedSpan.hpp @@ -22,6 +22,7 @@ namespace OpenVic { } constexpr forwardable_span::reference operator[](const IndexType _Off) const { + assert(_Off < size()); return forwardable_span::operator[](static_cast(type_safe::get(_Off))); } diff --git a/src/openvic-simulation/utility/ThreadPool.cpp b/src/openvic-simulation/utility/ThreadPool.cpp index e7ce93575..2fc169548 100644 --- a/src/openvic-simulation/utility/ThreadPool.cpp +++ b/src/openvic-simulation/utility/ThreadPool.cpp @@ -26,8 +26,8 @@ void ThreadPool::loop_until_cancelled( ) { IndexedFlatMap reusable_goods_mask { good_keys }; - memory::FixedVector reusable_country_map_0 { country_keys.size() }; - memory::FixedVector reusable_country_map_1 { country_keys.size() }; + memory::FixedVector reusable_country_map_0 { country_keys.size(), fixed_point_t::_0 }; + memory::FixedVector reusable_country_map_1 { country_keys.size(), fixed_point_t::_0 }; TypedSpan reusable_country_map_0_span { reusable_country_map_0 }; TypedSpan reusable_country_map_1_span { reusable_country_map_1 }; diff --git a/tests/src/types/FixedVector.cpp b/tests/src/types/FixedVector.cpp index 6c36f15b1..5ead40c0e 100644 --- a/tests/src/types/FixedVector.cpp +++ b/tests/src/types/FixedVector.cpp @@ -67,7 +67,7 @@ int DestructionCounter::destructor_count = 0; // A simple test case to check the basic constructor and accessors with a simple type. TEST_CASE("FixedVector Construction and basic accessors","[FixedVector]") { constexpr size_t capacity = 5; - FixedVector vec(capacity); + FixedVector vec { capacity }; // Initial state check CHECK(vec.size() == 0); @@ -111,7 +111,7 @@ TEST_CASE("FixedVector Generator constructor (tuple)","[FixedVector]") { // Test emplace_back, pop_back, and clear with a complex type. TEST_CASE("FixedVector Manipulation (emplace_back, pop_back, clear)","[FixedVector]") { constexpr size_t capacity = 4; - FixedVector vec(capacity); + FixedVector vec { capacity }; // Emplace elements with multiple arguments vec.emplace_back(1, "hello"); @@ -153,7 +153,7 @@ TEST_CASE("FixedVector Manipulation (emplace_back, pop_back, clear)","[FixedVect // Test that accessor methods return references to the same memory location TEST_CASE("FixedVector Accessor reference consistency","[FixedVector]") { constexpr size_t capacity = 3; - FixedVector vec(capacity); + FixedVector vec { capacity }; vec.emplace_back(1); CHECK(&vec.front() == &vec.back()); @@ -171,7 +171,7 @@ TEST_CASE("FixedVector Accessor reference consistency","[FixedVector]") { // Test with a non-copyable and non-movable type to ensure in-place construction. TEST_CASE("FixedVector Non-copyable, non-movable type","[FixedVector]") { constexpr size_t capacity = 2; - FixedVector vec(capacity); + FixedVector vec { capacity }; // This should work because emplace_back constructs in place const int value0 = 1; @@ -196,7 +196,7 @@ TEST_CASE("FixedVector Destruction, Clear, and Refill","[FixedVector]") { { // Use a scope to test the FixedVector's destructor - FixedVector vec(capacity); + FixedVector vec { capacity }; // Emplace a few objects vec.emplace_back();