Skip to content

Commit

Permalink
SegmentedRepository is now thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
drexlerd committed Dec 14, 2024
1 parent 701ab5b commit 271082a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 30 deletions.
59 changes: 52 additions & 7 deletions include/loki/details/utils/segmented_repository.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "loki/details/utils/segmented_vector.hpp"

#include <memory>
#include <shared_mutex>
#include <tuple>
#include <type_traits>
#include <unordered_set>
Expand All @@ -29,7 +30,7 @@
namespace loki
{

/// @brief `UniqueFactory` manages unique creation of objects
/// @brief `SegmentedRepository` is a thread-safe container for managing the unique creation of objects
/// in a persistent and efficient manner, utilizing a combination of unordered_set for
/// uniqueness checks and SegmentedVector for continuous and cache-efficient storage of value types.
/// @tparam T is the type.
Expand All @@ -45,6 +46,9 @@ class SegmentedRepository
// We use pre-allocated memory to store objects persistent.
SegmentedVector<T> m_persistent_vector;

// Mutex for synchronizing write operations
mutable std::shared_mutex m_mutex;

void range_check(size_t pos) const
{
if (pos >= size())
Expand All @@ -61,13 +65,33 @@ class SegmentedRepository
}
SegmentedRepository(const SegmentedRepository& other) = delete;
SegmentedRepository& operator=(const SegmentedRepository& other) = delete;
SegmentedRepository(SegmentedRepository&& other) = default;
SegmentedRepository& operator=(SegmentedRepository&& other) = default;
SegmentedRepository(SegmentedRepository&& other) noexcept :
m_uniqueness_set(std::move(other.m_uniqueness_set)),
m_persistent_vector(std::move(other.m_persistent_vector)),
m_mutex() // Create a new mutex for the moved object
{
}

SegmentedRepository& operator=(SegmentedRepository&& other) noexcept
{
if (this != &other)
{
std::unique_lock lock_this(m_mutex, std::defer_lock);
std::unique_lock lock_other(other.m_mutex, std::defer_lock);
std::lock(lock_this, lock_other);

m_uniqueness_set = std::move(other.m_uniqueness_set);
m_persistent_vector = std::move(other.m_persistent_vector);
}
return *this;
}

/// @brief Returns a pointer to an existing object or creates it before if it does not exist.
template<typename... Args>
T const* get_or_create(Args&&... args)
{
std::unique_lock lock(m_mutex); // Lock only for writing

/* Construct and insert the element in persistent memory. */

// Ensure that element with identifier i is stored at position i.
Expand Down Expand Up @@ -104,29 +128,50 @@ class SegmentedRepository
*/

/// @brief Returns a pointer to an existing object with the given pos.
// MT: no lock required, because elements are persistent.
T const* operator[](size_t pos) const
{
assert(pos < size());
return &(m_persistent_vector.at(pos));
}

/// @brief Returns a pointer to an existing object with the given pos.
/// MT: no lock required, because elements are persistent.
/// @param pos
/// @return
T const* at(size_t pos) const
{
range_check(pos);
return &(m_persistent_vector.at(pos));
}

auto begin() const { return m_persistent_vector.begin(); }
auto begin() const
{
std::shared_lock lock(m_mutex);
return m_persistent_vector.begin();
}

auto end() const { return m_persistent_vector.end(); }
auto end() const
{
std::shared_lock lock(m_mutex);
return m_persistent_vector.end();
}

const SegmentedVector<T>& get_storage() const { return m_persistent_vector; }
const SegmentedVector<T>& get_storage() const
{
std::shared_lock lock(m_mutex);
return m_persistent_vector;
}

/**
* Capacity
*/

size_t size() const { return m_persistent_vector.size(); }
size_t size() const
{
std::shared_lock lock(m_mutex);
return m_persistent_vector.size();
}
};

}
Expand Down
8 changes: 0 additions & 8 deletions src/ast/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ struct AssignOperatorIncreaseClass;
struct AssignOperatorDecreaseClass;
struct AssignOperatorClass;

struct NumericTermClass;

struct EffectClass;
struct EffectProductionLiteralClass;
struct EffectProductionNumericClass;
Expand Down Expand Up @@ -360,8 +358,6 @@ typedef x3::rule<AssignOperatorIncreaseClass, ast::AssignOperatorIncrease> assig
typedef x3::rule<AssignOperatorDecreaseClass, ast::AssignOperatorDecrease> assign_operator_decrease_type;
typedef x3::rule<AssignOperatorClass, ast::AssignOperator> assign_operator_type;

typedef x3::rule<NumericTermClass, ast::FunctionExpression> numeric_term_type;

typedef x3::rule<EffectClass, ast::Effect> effect_type;
typedef x3::rule<EffectProductionLiteralClass, ast::EffectProductionLiteral> effect_production_literal_type;
typedef x3::rule<EffectProductionNumericClass, ast::EffectProductionNumeric> effect_production_numeric_type;
Expand Down Expand Up @@ -551,8 +547,6 @@ BOOST_SPIRIT_DECLARE(assign_operator_assign_type,
assign_operator_decrease_type,
assign_operator_type)

BOOST_SPIRIT_DECLARE(numeric_term_type)

BOOST_SPIRIT_DECLARE(effect_type,
effect_production_literal_type,
effect_production_numeric_type,
Expand Down Expand Up @@ -743,8 +737,6 @@ parser::assign_operator_increase_type const& assign_operator_increase();
parser::assign_operator_decrease_type const& assign_operator_decrease();
parser::assign_operator_type const& assign_operator();

parser::numeric_term_type const& numeric_term();

parser::effect_type const& effect();
parser::effect_production_literal_type const& effect_production_literal();
parser::effect_production_numeric_type const& effect_production_numeric();
Expand Down
13 changes: 0 additions & 13 deletions src/ast/parser_def.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ assign_operator_increase_type const assign_operator_increase = "assign_operator_
assign_operator_decrease_type const assign_operator_decrease = "assign_operator_decrease";
assign_operator_type const assign_operator = "assign_operator";

numeric_term_type const numeric_term = "numeric_term";

effect_type const effect = "effect";
effect_production_literal_type const effect_production_literal = "effect_production_literal";
effect_production_numeric_type const effect_production_numeric = "effect_production_numeric";
Expand Down Expand Up @@ -393,9 +391,6 @@ const auto assign_operator_decrease_def = keyword_lit("decrease") > x3::attr(ast
const auto assign_operator_def =
assign_operator_assign | assign_operator_scale_up | assign_operator_scale_down | assign_operator_increase | assign_operator_decrease;

// For action cost effects only
const auto numeric_term_def = function_expression_number | function_expression_head;

const auto effect_def = ((lit('(') >> keyword_lit("and")) > *effect > lit(')')) | effect_composite | effect_production;
const auto effect_production_literal_def = literal;
const auto effect_production_numeric_def = (lit('(') >> assign_operator >> function_head >> function_expression) > lit(')');
Expand Down Expand Up @@ -588,8 +583,6 @@ BOOST_SPIRIT_DEFINE(assign_operator_assign,
assign_operator_decrease,
assign_operator)

BOOST_SPIRIT_DEFINE(numeric_term)

BOOST_SPIRIT_DEFINE(effect,
effect_production_literal,
effect_production_numeric,
Expand Down Expand Up @@ -965,10 +958,6 @@ struct AssignOperatorClass : x3::annotate_on_success
{
};

struct NumericTermClass : x3::annotate_on_success
{
};

struct EffectClass : x3::annotate_on_success
{
};
Expand Down Expand Up @@ -1318,8 +1307,6 @@ parser::assign_operator_increase_type const& assign_operator_increase() { return
parser::assign_operator_decrease_type const& assign_operator_decrease() { return parser::assign_operator_decrease; }
parser::assign_operator_type const& assign_operator() { return parser::assign_operator; }

parser::numeric_term_type const& numeric_term() { return parser::numeric_term; }

parser::effect_type const& effect() { return parser::effect; }
parser::effect_production_literal_type const& effect_production_literal() { return parser::effect_production_literal; }
parser::effect_production_numeric_type const& effect_production_numeric() { return parser::effect_production_numeric; }
Expand Down
2 changes: 0 additions & 2 deletions src/ast/parser_instantiations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ BOOST_SPIRIT_INSTANTIATE(assign_operator_increase_type, iterator_type, context_t
BOOST_SPIRIT_INSTANTIATE(assign_operator_decrease_type, iterator_type, context_type)
BOOST_SPIRIT_INSTANTIATE(assign_operator_type, iterator_type, context_type)

BOOST_SPIRIT_INSTANTIATE(numeric_term_type, iterator_type, context_type)

BOOST_SPIRIT_INSTANTIATE(effect_type, iterator_type, context_type)
BOOST_SPIRIT_INSTANTIATE(effect_production_literal_type, iterator_type, context_type)
BOOST_SPIRIT_INSTANTIATE(effect_production_numeric_type, iterator_type, context_type)
Expand Down

0 comments on commit 271082a

Please sign in to comment.