#pragma once #include "adminive/descriptor.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace adminive { template struct Mutex_Policy { using mutex_type = Mutex; }; template class Managed_Value; template class Managed_Field; namespace detail { template struct Is_Reference_Wrapper : std::false_type {}; template struct Is_Reference_Wrapper> : std::true_type {}; template concept Managed_Callback_Result = std::is_void_v || (!std::is_reference_v && !std::is_pointer_v && !Is_Reference_Wrapper>::value && !std::ranges::view>); template consteval std::size_t decimal_digits() { std::size_t result = 1; std::size_t current = Value; while(current >= 10) { current /= 10; ++result; } return result; } template consteval auto make_managed_key_text() { constexpr std::string_view prefix = "__adminive_"; constexpr std::size_t digits = decimal_digits(); std::array result{}; for(std::size_t position = 0; position < prefix.size(); ++position) { result[position] = prefix[position]; } std::size_t value = Index; for(std::size_t position = 0; position < digits; ++position) { result[prefix.size() + digits - position - 1] = static_cast('0' + value % 10); value /= 10; } return result; } template struct Managed_Key_Value { static constexpr auto text = make_managed_key_text(); constexpr std::string_view view() const noexcept { return {text.data(), text.size()}; } }; template struct Managed_Key_Attribute { using attribute_category = structive::Key_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = false; static constexpr Managed_Key_Value value{}; }; template consteval bool member_type_has_managed_writes() { using Value = std::remove_cvref_t; if constexpr(Described_Type) { return described_type_has_managed_writes(); } return false; } template inline constexpr bool managed_field_writable_v = Field::managed_writable || member_type_has_managed_writes(); template consteval bool field_requires_synchronization(); template consteval bool member_type_requires_synchronization() { using Value = std::remove_cvref_t; if constexpr(Described_Type) { using Fields = Descriptor_Fields; return [](std::index_sequence) { return (field_requires_synchronization>() || ...); }(std::make_index_sequence>{}); } return false; } template consteval bool field_requires_synchronization() { if constexpr(Field::managed_writable) { return Field::synchronized; } return member_type_requires_synchronization(); } template const auto& managed_descriptor_field() { static const auto descriptor = describe(); return std::get(descriptor.fields()); } template struct Managed_Field_Accessor { using object_type = Managed; using value_type = typename Field::member_type; struct storage_identity {}; using dependency_spec = structive::No_Property_Dependencies; static constexpr bool readable = true; static constexpr bool writable = managed_field_writable_v; static constexpr bool synchronized_view_read = false; static constexpr bool trusted_object_access = false; decltype(auto) read(const object_type& object) const noexcept(noexcept(managed_descriptor_field().get( object.unsafe_value()))) { return managed_descriptor_field().get( object.unsafe_value()); } decltype(auto) read(object_type& object) const noexcept(noexcept(managed_descriptor_field().get( object.unsafe_value()))) { return managed_descriptor_field().get( object.unsafe_value()); } template void write(object_type& object, Value&& value) const requires writable && requires { managed_descriptor_field().set( object.unsafe_value(), std::forward(value)); } { managed_descriptor_field().set( object.unsafe_value(), std::forward(value)); } }; template auto make_structive_property() { using Accessor = Managed_Field_Accessor; using Key = Managed_Key_Attribute; if constexpr(managed_field_writable_v) { using Capability = structive::Property_Capability_Attribute; return structive::Property_Descriptor{{}, {Key{}, Capability{}}}; } else { using Capability = structive::Property_Capability_Attribute; return structive::Property_Descriptor{{}, {Key{}, Capability{}}}; } } template auto make_managed_schema_impl(std::index_sequence) { using Fields = Descriptor_Fields; structive::Synchronization_Plan plan; ([&] { using Field = std::tuple_element_t; if constexpr(managed_field_writable_v && !field_requires_synchronization()) { plan.unsynchronized(Managed_Key_Attribute::value.view()); } }(), ...); return structive::object(std::move(plan), make_structive_property, Indexes>()...); } template auto make_managed_schema() { return make_managed_schema_impl(std::make_index_sequence>>{}); } template consteval std::size_t described_member_index() { using Fields = Descriptor_Fields; if constexpr(Index == std::tuple_size_v) { return Index; } else { using Field = std::tuple_element_t; using Accessor = typename Field::accessor_type; if constexpr(requires { Accessor::member; } && std::same_as, decltype(Member)>) { if constexpr(Accessor::member == Member) { return Index; } } return described_member_index(); } } template consteval bool managed_member_path_writable() { static_assert(Described_Type>); constexpr auto index = described_member_index, Member>(); using Field = Descriptor_Field, index>; if constexpr(sizeof...(Rest) == 0) { return Field::managed_writable; } else { return managed_member_path_writable(); } } template consteval bool managed_member_path_requires_synchronization() { static_assert(Described_Type>); constexpr auto index = described_member_index, Member>(); using Field = Descriptor_Field, index>; if constexpr(Field::managed_writable) { return Field::synchronized; } else if constexpr(sizeof...(Rest) == 0) { return false; } else { return managed_member_path_requires_synchronization(); } } template consteval bool managed_path_writable() { using Field = Descriptor_Field; if constexpr(sizeof...(Members) == 0) { return Field::managed_writable; } else { return managed_member_path_writable(); } } template consteval bool managed_path_requires_synchronization() { using Field = Descriptor_Field; if constexpr(Field::managed_writable) { return Field::synchronized; } else if constexpr(sizeof...(Members) == 0) { return false; } else { return managed_member_path_requires_synchronization(); } } template decltype(auto) path_value(Object& object) { auto&& next = object.*Member; if constexpr(sizeof...(Rest) == 0) { return std::forward(next); } else { return path_value(next); } } template decltype(auto) path_value(const Object& object) { auto&& next = object.*Member; if constexpr(sizeof...(Rest) == 0) { return std::forward(next); } else { return path_value(next); } } template decltype(auto) managed_path_value(T& object) { using Field = Descriptor_Field; auto&& root = managed_descriptor_field().get(object); if constexpr(sizeof...(Members) == 0) { return std::forward(root); } else { return path_value(root); } } template decltype(auto) managed_path_value(const T& object) { using Field = Descriptor_Field; auto&& root = managed_descriptor_field().get(object); if constexpr(sizeof...(Members) == 0) { return std::forward(root); } else { return path_value(root); } } template auto managed_key_array_impl(std::index_sequence) { return std::array{Managed_Key_Attribute::value.view()...}; } template const auto& managed_key_array() { static const auto value = managed_key_array_impl(std::make_index_sequence>>{}); return value; } } } namespace structive { template struct Type_Descriptor> { static auto get() { return adminive::detail::make_managed_schema, T>(); } }; } namespace adminive { template class Managed_Value : public structive::Property_Object, Policy> { using Base = structive::Property_Object, Policy>; public: using value_type = T; using policy_type = Policy; Managed_Value() requires std::default_initializable = default; explicit Managed_Value(T value) : value_(std::move(value)) {} explicit Managed_Value(structive::Property_Synchronization synchronization) : Base(std::move(synchronization)) {} Managed_Value(T value, structive::Property_Synchronization synchronization) : Base(std::move(synchronization)), value_(std::move(value)) {} Managed_Value(const Managed_Value&) requires std::copy_constructible = default; Managed_Value(Managed_Value&&) noexcept(std::is_nothrow_move_constructible_v) requires std::move_constructible = default; Managed_Value& operator=(const Managed_Value&) requires std::is_copy_assignable_v = default; Managed_Value& operator=(Managed_Value&&) noexcept(std::is_nothrow_move_assignable_v) requires std::is_move_assignable_v = default; T& unsafe_value() noexcept { return value_; } const T& unsafe_value() const noexcept { return value_; } template decltype(auto) read(Function&& function) const requires std::invocable && detail::Managed_Callback_Result> { return this->with_all_readable_locked([&](const auto&) -> decltype(auto) { return std::invoke(std::forward(function), std::as_const(value_)); }); } template decltype(auto) write(Function&& function) requires std::invocable && detail::Managed_Callback_Result> { using Result = std::invoke_result_t; if constexpr(std::is_void_v) { this->with_all_writable_locked([&](auto&) { std::invoke(std::forward(function), value_); }); } else { using Value_Result = std::remove_cvref_t; std::optional result; this->with_all_writable_locked([&](auto&) { result.emplace(std::invoke(std::forward(function), value_)); }); return Value_Result(std::move(*result)); } } T snapshot() const requires std::copy_constructible { return read([](const T& value) { return value; }); } template auto member() { constexpr auto index = detail::described_member_index(); static_assert(index < std::tuple_size_v>); return Managed_Field{*this}; } template auto member() const { constexpr auto index = detail::described_member_index(); static_assert(index < std::tuple_size_v>); return Managed_Field{*this}; } template auto field() { static_assert(Index < std::tuple_size_v>); return Managed_Field{*this}; } template auto field() const { static_assert(Index < std::tuple_size_v>); return Managed_Field{*this}; } private: T value_{}; }; template class Managed_Field { using Owner = std::remove_const_t; using Root = typename Owner::value_type; public: using owner_type = Managed; using value_type = std::remove_cvref_t(std::declval()))>; explicit Managed_Field(Managed& owner) : owner_(&owner) {} template decltype(auto) read(Function&& function) const requires std::invocable && detail::Managed_Callback_Result> { return owner_->template with_read_index([&](const auto& root_value) -> decltype(auto) { if constexpr(sizeof...(Members) == 0) return std::invoke(std::forward(function), root_value); else return std::invoke(std::forward(function), detail::path_value(root_value)); }); } template decltype(auto) write(Function&& function) requires (!std::is_const_v) && (detail::managed_path_writable()) && std::invocable && detail::Managed_Callback_Result> { if constexpr(detail::managed_path_requires_synchronization()) { const auto key = detail::Managed_Key_Attribute::value.view(); auto guard = owner_->lock_unique({key}); auto& value = detail::managed_path_value(owner_->unsafe_value()); return std::invoke(std::forward(function), value); } else { auto& value = detail::managed_path_value(owner_->unsafe_value()); return std::invoke(std::forward(function), value); } } value_type snapshot() const requires std::copy_constructible { return read([](const value_type& value) { return value; }); } template auto member() requires (!std::is_const_v) { return Managed_Field{*owner_}; } template auto member() const { return Managed_Field{*owner_}; } Managed& owner() const noexcept { return *owner_; } private: Managed* owner_; }; template struct Is_Managed_Value : std::false_type {}; template struct Is_Managed_Value> : std::true_type {}; template concept Managed_Value_Type = Is_Managed_Value>::value; template struct Is_Managed_Field : std::false_type {}; template struct Is_Managed_Field> : std::true_type {}; template concept Managed_Field_Type = Is_Managed_Field>::value; }