Files
Structive/core/include/structive/property/synchronization.hpp
T
2026-08-07 16:21:44 +08:00

169 lines
6.0 KiB
C++

#pragma once
#include <array>
#include <cstddef>
#include <concepts>
#include <initializer_list>
#include <limits>
#include <span>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
namespace structive {
enum class Synchronization_Default {
independent,
shared,
unsynchronized
};
struct Sync_Default_Rule {
Synchronization_Default value{Synchronization_Default::independent};
};
struct Sync_Property_Rule {
enum class Mode {
independent,
unsynchronized
};
Mode mode{Mode::independent};
std::string property;
};
struct Sync_Group_Rule {
std::string name;
std::vector<std::string> properties;
};
template <auto Member, Sync_Property_Rule::Mode Mode>
struct Sync_Member_Rule {
static constexpr auto member = Member;
static constexpr auto mode = Mode;
};
template <auto... Members>
struct Sync_Member_Group_Rule {
static_assert(sizeof...(Members) > 0);
std::string name;
};
inline constexpr Sync_Default_Rule sync_all_independent{Synchronization_Default::independent};
inline constexpr Sync_Default_Rule sync_all_shared{Synchronization_Default::shared};
inline constexpr Sync_Default_Rule sync_all_unsynchronized{Synchronization_Default::unsynchronized};
inline Sync_Property_Rule sync_independent(std::string_view property) {
return {Sync_Property_Rule::Mode::independent, std::string(property)};
}
inline Sync_Property_Rule sync_unsynchronized(std::string_view property) {
return {Sync_Property_Rule::Mode::unsynchronized, std::string(property)};
}
template <auto Member>
constexpr auto sync_independent() {
return Sync_Member_Rule<Member, Sync_Property_Rule::Mode::independent>{};
}
template <auto Member>
constexpr auto sync_unsynchronized() {
return Sync_Member_Rule<Member, Sync_Property_Rule::Mode::unsynchronized>{};
}
template <auto... Members>
Sync_Member_Group_Rule<Members...> sync_group(std::string_view name) {
return {std::string(name)};
}
template <class... Properties>
Sync_Group_Rule sync_group(std::string_view name, Properties&&... properties) requires (std::convertible_to<Properties, std::string_view> && ...) {
Sync_Group_Rule rule;
rule.name = name;
rule.properties.reserve(sizeof...(Properties));
(rule.properties.emplace_back(std::string_view(std::forward<Properties>(properties))), ...);
return rule;
}
class Synchronization_Plan {
Synchronization_Default default_mode_{Synchronization_Default::independent};
std::vector<Sync_Property_Rule> property_rules_;
std::vector<Sync_Group_Rule> group_rules_;
public:
using synchronization_plan_tag = void;
Synchronization_Plan() = default;
explicit Synchronization_Plan(Synchronization_Default mode) : default_mode_(mode) {}
Synchronization_Default default_mode() const noexcept {
return default_mode_;
}
const auto& property_rules() const noexcept {
return property_rules_;
}
const auto& group_rules() const noexcept {
return group_rules_;
}
Synchronization_Plan& set_default(Synchronization_Default mode) {
default_mode_ = mode;
return *this;
}
Synchronization_Plan& independent(std::string_view property) {
property_rules_.push_back(sync_independent(property));
return *this;
}
Synchronization_Plan& unsynchronized(std::string_view property) {
property_rules_.push_back(sync_unsynchronized(property));
return *this;
}
Synchronization_Plan& group(std::string_view name, std::span<const std::string_view> properties) {
Sync_Group_Rule rule;
rule.name = name;
rule.properties.reserve(properties.size());
for (auto property : properties) {
rule.properties.emplace_back(property);
}
group_rules_.push_back(std::move(rule));
return *this;
}
Synchronization_Plan& group(std::string_view name, std::initializer_list<std::string_view> properties) {
return group(name, std::span<const std::string_view>{properties.begin(), properties.size()});
}
Synchronization_Plan& apply(Sync_Default_Rule rule) {
default_mode_ = rule.value;
return *this;
}
Synchronization_Plan& apply(Sync_Property_Rule rule) {
property_rules_.push_back(std::move(rule));
return *this;
}
Synchronization_Plan& apply(Sync_Group_Rule rule) {
group_rules_.push_back(std::move(rule));
return *this;
}
};
template <class Type>
concept Synchronization_Plan_Type = requires {
typename Type::synchronization_plan_tag;
};
template <class Type>
concept Runtime_Synchronization_Rule = std::same_as<std::remove_cvref_t<Type>, Sync_Default_Rule> || std::same_as<std::remove_cvref_t<Type>, Sync_Property_Rule> || std::same_as<std::remove_cvref_t<Type>, Sync_Group_Rule>;
template <class... Rules>
struct Synchronization_Spec {
using synchronization_spec_tag = void;
std::tuple<Rules...> rules;
};
template <class Type>
concept Synchronization_Spec_Type = requires {
typename Type::synchronization_spec_tag;
};
template <class Type>
concept Synchronization_Source_Type = Synchronization_Plan_Type<Type> || Synchronization_Spec_Type<Type>;
template <class... Rules>
auto synchronization(Rules&&... rules) {
if constexpr ((Runtime_Synchronization_Rule<Rules> && ...)) {
Synchronization_Plan plan;
(plan.apply(std::forward<Rules>(rules)), ...);
return plan;
} else {
return Synchronization_Spec<std::decay_t<Rules>...>{{std::forward<Rules>(rules)...}};
}
}
template <std::size_t Property_Count>
struct Resolved_Synchronization_Plan {
static constexpr std::size_t unsynchronized_slot = std::numeric_limits<std::size_t>::max();
std::array<std::size_t, Property_Count> lock_slots{};
std::size_t lock_count{};
constexpr std::size_t slot(std::size_t property_index) const noexcept {
return lock_slots[property_index];
}
constexpr bool uses_lock(std::size_t property_index) const noexcept {
return slot(property_index) != unsynchronized_slot;
}
};
}