|
|
|
@@ -79,22 +79,6 @@ public:
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
enum class Managed_Access_Mode {
|
|
|
|
|
external,
|
|
|
|
|
persistence
|
|
|
|
|
};
|
|
|
|
|
namespace detail {
|
|
|
|
|
enum class Access_Kind {
|
|
|
|
|
intrinsic,
|
|
|
|
|
external,
|
|
|
|
|
persistence
|
|
|
|
|
};
|
|
|
|
|
constexpr Access_Kind access_kind(Managed_Access_Mode mode) noexcept {
|
|
|
|
|
return mode == Managed_Access_Mode::external ? Access_Kind::external : Access_Kind::persistence;
|
|
|
|
|
}
|
|
|
|
|
template <Managed_Access_Mode Mode>
|
|
|
|
|
inline constexpr Access_Kind access_kind_v = Mode == Managed_Access_Mode::external ? Access_Kind::external : Access_Kind::persistence;
|
|
|
|
|
}
|
|
|
|
|
enum class Runtime_Access_Result {
|
|
|
|
|
ok,
|
|
|
|
|
unknown_property,
|
|
|
|
@@ -107,8 +91,8 @@ class Property_Object_Base {
|
|
|
|
|
struct Runtime_Interface {
|
|
|
|
|
const std::type_info& (*object_type)() noexcept;
|
|
|
|
|
std::size_t (*property_count)() noexcept;
|
|
|
|
|
Runtime_Access_Result (*read)(const Property_Object_Base&, detail::Access_Kind, std::string_view, void*, Runtime_Read_Callback);
|
|
|
|
|
Runtime_Access_Result (*write)(Property_Object_Base&, detail::Access_Kind, std::string_view, const std::type_info&, const void*);
|
|
|
|
|
Runtime_Access_Result (*read)(const Property_Object_Base&, std::string_view, void*, Runtime_Read_Callback);
|
|
|
|
|
Runtime_Access_Result (*write)(Property_Object_Base&, std::string_view, const std::type_info&, const void*);
|
|
|
|
|
};
|
|
|
|
|
const Runtime_Interface* runtime_interface_{};
|
|
|
|
|
protected:
|
|
|
|
@@ -128,26 +112,12 @@ public:
|
|
|
|
|
return runtime_interface_->property_count();
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result runtime_read(std::string_view key, void* context, Runtime_Read_Callback callback) const {
|
|
|
|
|
return runtime_interface_->read(*this, detail::Access_Kind::intrinsic, key, context, callback);
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result runtime_read(Managed_Access_Mode mode, std::string_view key, void* context, Runtime_Read_Callback callback) const {
|
|
|
|
|
return runtime_interface_->read(*this, detail::access_kind(mode), key, context, callback);
|
|
|
|
|
return runtime_interface_->read(*this, key, context, callback);
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result runtime_write(std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
return runtime_interface_->write(*this, detail::Access_Kind::intrinsic, key, value_type, value);
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result runtime_write(Managed_Access_Mode mode, std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
return runtime_interface_->write(*this, detail::access_kind(mode), key, value_type, value);
|
|
|
|
|
return runtime_interface_->write(*this, key, value_type, value);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
namespace detail {
|
|
|
|
|
template <Access_Kind Mode, class Schema, std::size_t Index>
|
|
|
|
|
inline constexpr bool property_read_allowed_v = Mode == Access_Kind::intrinsic ? Schema::template property_type<Index>::readable : Mode == Access_Kind::external ? external_readable_v<Schema, Index> : persistence_storable_v<Schema, Index>;
|
|
|
|
|
template <Access_Kind Mode, class Schema, std::size_t Index>
|
|
|
|
|
inline constexpr bool property_write_allowed_v = Mode == Access_Kind::intrinsic ? Schema::template property_type<Index>::writable : Mode == Access_Kind::external ? external_writable_v<Schema, Index> : persistence_loadable_v<Schema, Index>;
|
|
|
|
|
template <Access_Kind Mode, class Schema, std::size_t Index>
|
|
|
|
|
inline constexpr bool property_visible_v = property_read_allowed_v<Mode, Schema, Index> || property_write_allowed_v<Mode, Schema, Index>;
|
|
|
|
|
}
|
|
|
|
|
struct Property_Synchronization {
|
|
|
|
|
Synchronization_Plan plan;
|
|
|
|
|
};
|
|
|
|
@@ -249,23 +219,20 @@ private:
|
|
|
|
|
}
|
|
|
|
|
count = write;
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
static bool runtime_property_readable(std::size_t index) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static const auto table = []<std::size_t... Index>(std::index_sequence<Index...>) {
|
|
|
|
|
return std::array<bool, Schema::property_count>{detail::property_read_allowed_v<Mode, Schema, Index>...};
|
|
|
|
|
return std::array<bool, Schema::property_count>{Schema::template property_type<Index>::readable...};
|
|
|
|
|
}(std::make_index_sequence<Schema::property_count>{});
|
|
|
|
|
return table[index];
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
static bool runtime_property_visible(std::size_t index) {
|
|
|
|
|
static bool runtime_property_writable(std::size_t index) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static const auto table = []<std::size_t... Index>(std::index_sequence<Index...>) {
|
|
|
|
|
return std::array<bool, Schema::property_count>{detail::property_visible_v<Mode, Schema, Index>...};
|
|
|
|
|
return std::array<bool, Schema::property_count>{Schema::template property_type<Index>::writable...};
|
|
|
|
|
}(std::make_index_sequence<Schema::property_count>{});
|
|
|
|
|
return table[index];
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Dynamic_Lock_Targets collect_dynamic_lock_targets(std::span<const std::string_view> keys, bool shared_access) const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
Dynamic_Lock_Targets targets;
|
|
|
|
@@ -276,9 +243,9 @@ private:
|
|
|
|
|
if (!index) {
|
|
|
|
|
throw std::invalid_argument("Unknown property: " + std::string(key));
|
|
|
|
|
}
|
|
|
|
|
bool allowed = shared_access ? runtime_property_readable<Mode>(*index) : runtime_property_visible<Mode>(*index);
|
|
|
|
|
bool allowed = shared_access ? runtime_property_readable(*index) : runtime_property_writable(*index);
|
|
|
|
|
if (!allowed) {
|
|
|
|
|
throw std::invalid_argument("Property is not accessible through this view: " + std::string(key));
|
|
|
|
|
throw std::invalid_argument(std::string(shared_access ? "Property is not readable: " : "Property is not writable: ") + std::string(key));
|
|
|
|
|
}
|
|
|
|
|
auto lock_slot = slot(*index);
|
|
|
|
|
if (lock_slot == Resolved_Synchronization_View::unsynchronized_slot) {
|
|
|
|
@@ -293,10 +260,10 @@ private:
|
|
|
|
|
targets.unsynchronized_properties.erase(std::unique(targets.unsynchronized_properties.begin(), targets.unsynchronized_properties.end()), targets.unsynchronized_properties.end());
|
|
|
|
|
return targets;
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, bool Shared_Access, std::size_t... Index>
|
|
|
|
|
template <bool Shared_Access, std::size_t... Index>
|
|
|
|
|
Static_Lock_Targets<sizeof...(Index)> collect_static_lock_targets() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(((Shared_Access ? detail::property_read_allowed_v<Mode, Schema, Index> : detail::property_visible_v<Mode, Schema, Index>) && ...));
|
|
|
|
|
static_assert(((Shared_Access ? Schema::template property_type<Index>::readable : Schema::template property_type<Index>::writable) && ...));
|
|
|
|
|
Static_Lock_Targets<sizeof...(Index)> targets;
|
|
|
|
|
auto collect = [&]<std::size_t Property_Index>() {
|
|
|
|
|
auto lock_slot = slot(Property_Index);
|
|
|
|
@@ -311,12 +278,12 @@ private:
|
|
|
|
|
sort_unique_prefix(targets.unsynchronized_properties, targets.unsynchronized_count);
|
|
|
|
|
return targets;
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, bool Shared_Access>
|
|
|
|
|
template <bool Shared_Access>
|
|
|
|
|
auto collect_all_static_lock_targets() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
Static_Lock_Targets<Schema::property_count> targets;
|
|
|
|
|
auto collect = [&]<std::size_t Index>() {
|
|
|
|
|
constexpr bool allowed = Shared_Access ? detail::property_read_allowed_v<Mode, Schema, Index> : detail::property_write_allowed_v<Mode, Schema, Index>;
|
|
|
|
|
constexpr bool allowed = Shared_Access ? Schema::template property_type<Index>::readable : Schema::template property_type<Index>::writable;
|
|
|
|
|
if constexpr (allowed) {
|
|
|
|
|
auto lock_slot = slot(Index);
|
|
|
|
|
if (lock_slot == Resolved_Synchronization_View::unsynchronized_slot) {
|
|
|
|
@@ -349,7 +316,6 @@ private:
|
|
|
|
|
const auto& descriptor = type_descriptor<Derived>().template property<Index>();
|
|
|
|
|
descriptor.accessor.write(static_cast<Derived&>(*this), std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
class Single_Read_View {
|
|
|
|
|
const Property_Object* owner_{};
|
|
|
|
|
std::size_t property_index_{};
|
|
|
|
@@ -361,6 +327,11 @@ private:
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
using Property = typename Schema::template property_type<index>;
|
|
|
|
|
static_assert(Property::readable);
|
|
|
|
|
if constexpr (!Property::writable && !Property::accessor_type::synchronized_view_read) {
|
|
|
|
|
return owner_->template read_unlocked<index>(*this);
|
|
|
|
|
}
|
|
|
|
|
if (owner_->slot(index) != lock_slot_ || (lock_slot_ == Resolved_Synchronization_View::unsynchronized_slot && index != property_index_)) {
|
|
|
|
|
throw std::logic_error("Computed property reads outside its synchronization slot");
|
|
|
|
|
}
|
|
|
|
@@ -371,23 +342,28 @@ private:
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
using Property = typename Schema::template property_type<index>;
|
|
|
|
|
static_assert(Property::readable);
|
|
|
|
|
if constexpr (!Property::writable && !Property::accessor_type::synchronized_view_read) {
|
|
|
|
|
return owner_->template read_unlocked<index>(*this);
|
|
|
|
|
}
|
|
|
|
|
if (owner_->slot(index) != lock_slot_ || (lock_slot_ == Resolved_Synchronization_View::unsynchronized_slot && index != property_index_)) {
|
|
|
|
|
throw std::logic_error("Computed property reads outside its synchronization slot");
|
|
|
|
|
}
|
|
|
|
|
return owner_->template read_unlocked<index>(*this);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <detail::Access_Kind Mode, std::size_t Index>
|
|
|
|
|
template <std::size_t Index>
|
|
|
|
|
auto read_one() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(detail::property_read_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::readable);
|
|
|
|
|
using Property = typename Schema::template property_type<Index>;
|
|
|
|
|
using Value = typename Property::value_type;
|
|
|
|
|
if constexpr (!uses_real_mutexes && !Property::accessor_type::synchronized_view_read) {
|
|
|
|
|
if constexpr ((!Property::writable && !Property::accessor_type::synchronized_view_read) || (!uses_real_mutexes && !Property::accessor_type::synchronized_view_read)) {
|
|
|
|
|
return Value(read_unlocked<Index>(*this));
|
|
|
|
|
}
|
|
|
|
|
auto lock_slot = slot(Index);
|
|
|
|
|
Single_Read_View<Mode> view{*this, Index, lock_slot};
|
|
|
|
|
Single_Read_View view{*this, Index, lock_slot};
|
|
|
|
|
if constexpr (!uses_real_mutexes) {
|
|
|
|
|
return Value(read_unlocked<Index>(view));
|
|
|
|
|
}
|
|
|
|
@@ -397,10 +373,10 @@ private:
|
|
|
|
|
std::shared_lock lock{mutex(lock_slot)};
|
|
|
|
|
return Value(read_unlocked<Index>(view));
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, std::size_t Index, class Value>
|
|
|
|
|
template <std::size_t Index, class Value>
|
|
|
|
|
void write_one(Value&& value) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(detail::property_write_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::writable);
|
|
|
|
|
if constexpr (!uses_real_mutexes) {
|
|
|
|
|
write_unlocked<Index>(std::forward<Value>(value));
|
|
|
|
|
return;
|
|
|
|
@@ -414,7 +390,6 @@ private:
|
|
|
|
|
write_unlocked<Index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
class Basic_Read_Guard {
|
|
|
|
|
const Property_Object* owner_{};
|
|
|
|
|
std::vector<std::size_t> slots_;
|
|
|
|
@@ -441,7 +416,7 @@ private:
|
|
|
|
|
decltype(auto) get_index() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_read_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::readable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -462,7 +437,6 @@ private:
|
|
|
|
|
return get_index<index>();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
class Basic_Write_Guard {
|
|
|
|
|
Property_Object* owner_{};
|
|
|
|
|
std::vector<std::size_t> slots_;
|
|
|
|
@@ -489,7 +463,7 @@ private:
|
|
|
|
|
decltype(auto) get_index() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_read_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::readable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -513,7 +487,7 @@ private:
|
|
|
|
|
void set_index(Value&& value) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_write_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::writable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -534,7 +508,7 @@ private:
|
|
|
|
|
set_index<index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <detail::Access_Kind Mode, std::size_t Capacity>
|
|
|
|
|
template <std::size_t Capacity>
|
|
|
|
|
class Static_Read_Guard {
|
|
|
|
|
const Property_Object* owner_{};
|
|
|
|
|
Static_Lock_Targets<Capacity> targets_;
|
|
|
|
@@ -559,7 +533,7 @@ private:
|
|
|
|
|
decltype(auto) get_index() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_read_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::readable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -580,7 +554,7 @@ private:
|
|
|
|
|
return get_index<index>();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <detail::Access_Kind Mode, std::size_t Capacity>
|
|
|
|
|
template <std::size_t Capacity>
|
|
|
|
|
class Static_Write_Guard {
|
|
|
|
|
Property_Object* owner_{};
|
|
|
|
|
Static_Lock_Targets<Capacity> targets_;
|
|
|
|
@@ -605,7 +579,7 @@ private:
|
|
|
|
|
decltype(auto) get_index() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_read_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::readable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -629,7 +603,7 @@ private:
|
|
|
|
|
void set_index(Value&& value) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert(Index < Schema::property_count);
|
|
|
|
|
static_assert(detail::property_write_allowed_v<Mode, Schema, Index>);
|
|
|
|
|
static_assert(Schema::template property_type<Index>::writable);
|
|
|
|
|
if (!holds(Index)) {
|
|
|
|
|
throw std::logic_error("Property is outside the held synchronization set");
|
|
|
|
|
}
|
|
|
|
@@ -651,42 +625,38 @@ private:
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
public:
|
|
|
|
|
using Intrinsic_Read_Guard = Basic_Read_Guard<detail::Access_Kind::intrinsic>;
|
|
|
|
|
using Intrinsic_Write_Guard = Basic_Write_Guard<detail::Access_Kind::intrinsic>;
|
|
|
|
|
template <Managed_Access_Mode Mode>
|
|
|
|
|
using Read_Guard = Basic_Read_Guard<detail::access_kind_v<Mode>>;
|
|
|
|
|
template <Managed_Access_Mode Mode>
|
|
|
|
|
using Write_Guard = Basic_Write_Guard<detail::access_kind_v<Mode>>;
|
|
|
|
|
using Read_Guard = Basic_Read_Guard;
|
|
|
|
|
using Write_Guard = Basic_Write_Guard;
|
|
|
|
|
private:
|
|
|
|
|
template <detail::Access_Kind Mode, class Function>
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable_impl(Function&& function) const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
const auto& schema = type_descriptor<Derived>();
|
|
|
|
|
schema.for_each_property([&](auto index, const auto& descriptor) {
|
|
|
|
|
constexpr std::size_t property_index = decltype(index)::value;
|
|
|
|
|
if constexpr (detail::property_read_allowed_v<Mode, Schema, property_index>) {
|
|
|
|
|
auto value = read_one<Mode, property_index>();
|
|
|
|
|
if constexpr (Schema::template property_type<property_index>::readable) {
|
|
|
|
|
auto value = read_one<property_index>();
|
|
|
|
|
std::invoke(function, index, descriptor, value);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, class Function>
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable_locked_impl(Function&& function) const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
auto targets = collect_all_static_lock_targets<Mode, true>();
|
|
|
|
|
Static_Read_Guard<Mode, Schema::property_count> guard{*this, std::move(targets)};
|
|
|
|
|
auto targets = collect_all_static_lock_targets<true>();
|
|
|
|
|
Static_Read_Guard<Schema::property_count> guard{*this, std::move(targets)};
|
|
|
|
|
type_descriptor<Derived>().for_each_property([&](auto index, const auto& descriptor) {
|
|
|
|
|
constexpr std::size_t property_index = decltype(index)::value;
|
|
|
|
|
if constexpr (detail::property_read_allowed_v<Mode, Schema, property_index>) {
|
|
|
|
|
if constexpr (Schema::template property_type<property_index>::readable) {
|
|
|
|
|
std::invoke(function, index, descriptor, guard.template get_index<property_index>());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, class Function>
|
|
|
|
|
template <class Function>
|
|
|
|
|
void with_all_writable_locked_impl(Function&& function) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
auto targets = collect_all_static_lock_targets<Mode, false>();
|
|
|
|
|
Static_Write_Guard<Mode, Schema::property_count> guard{*this, std::move(targets)};
|
|
|
|
|
auto targets = collect_all_static_lock_targets<false>();
|
|
|
|
|
Static_Write_Guard<Schema::property_count> guard{*this, std::move(targets)};
|
|
|
|
|
std::invoke(std::forward<Function>(function), guard);
|
|
|
|
|
}
|
|
|
|
|
static const std::type_info& runtime_object_type_impl() noexcept {
|
|
|
|
@@ -696,63 +666,64 @@ private:
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
return Schema::property_count;
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Runtime_Access_Result runtime_read_mode(std::string_view key, void* context, Runtime_Read_Callback callback) const {
|
|
|
|
|
Runtime_Access_Result runtime_read_impl_local(std::string_view key, void* context, Runtime_Read_Callback callback) const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
auto index = schema_property_index<Schema>(key);
|
|
|
|
|
if (!index) {
|
|
|
|
|
return Runtime_Access_Result::unknown_property;
|
|
|
|
|
}
|
|
|
|
|
if (!runtime_property_readable<Mode>(*index)) {
|
|
|
|
|
if (!runtime_property_readable(*index)) {
|
|
|
|
|
return Runtime_Access_Result::not_readable;
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result result = Runtime_Access_Result::unknown_property;
|
|
|
|
|
visit_schema_property(type_descriptor<Derived>(), key, [&](auto property_index_constant, const auto&) {
|
|
|
|
|
constexpr std::size_t property_index = decltype(property_index_constant)::value;
|
|
|
|
|
using Value = typename Schema::template property_type<property_index>::value_type;
|
|
|
|
|
auto lock_slot = slot(property_index);
|
|
|
|
|
Single_Read_View<Mode> view{*this, property_index, lock_slot};
|
|
|
|
|
auto emit = [&] {
|
|
|
|
|
if constexpr (std::is_reference_v<decltype(read_unlocked<property_index>(view))>) {
|
|
|
|
|
auto&& value = read_unlocked<property_index>(view);
|
|
|
|
|
using Property = typename Schema::template property_type<property_index>;
|
|
|
|
|
using Value = typename Property::value_type;
|
|
|
|
|
if constexpr (!Property::writable && !Property::accessor_type::synchronized_view_read) {
|
|
|
|
|
if constexpr (std::is_reference_v<decltype(read_unlocked<property_index>(*this))>) {
|
|
|
|
|
auto&& value = read_unlocked<property_index>(*this);
|
|
|
|
|
callback(context, property_index, key, typeid(Value), std::addressof(value));
|
|
|
|
|
} else {
|
|
|
|
|
Value value = read_unlocked<property_index>(view);
|
|
|
|
|
Value value = read_unlocked<property_index>(*this);
|
|
|
|
|
callback(context, property_index, key, typeid(Value), std::addressof(value));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if constexpr (!uses_real_mutexes) {
|
|
|
|
|
emit();
|
|
|
|
|
} else if (lock_slot == Resolved_Synchronization_View::unsynchronized_slot) {
|
|
|
|
|
emit();
|
|
|
|
|
} else {
|
|
|
|
|
std::shared_lock lock{mutex(lock_slot)};
|
|
|
|
|
emit();
|
|
|
|
|
auto lock_slot = slot(property_index);
|
|
|
|
|
Single_Read_View view{*this, property_index, lock_slot};
|
|
|
|
|
auto emit = [&] {
|
|
|
|
|
if constexpr (std::is_reference_v<decltype(read_unlocked<property_index>(view))>) {
|
|
|
|
|
auto&& value = read_unlocked<property_index>(view);
|
|
|
|
|
callback(context, property_index, key, typeid(Value), std::addressof(value));
|
|
|
|
|
} else {
|
|
|
|
|
Value value = read_unlocked<property_index>(view);
|
|
|
|
|
callback(context, property_index, key, typeid(Value), std::addressof(value));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if constexpr (!uses_real_mutexes) {
|
|
|
|
|
emit();
|
|
|
|
|
} else if (lock_slot == Resolved_Synchronization_View::unsynchronized_slot) {
|
|
|
|
|
emit();
|
|
|
|
|
} else {
|
|
|
|
|
std::shared_lock lock{mutex(lock_slot)};
|
|
|
|
|
emit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result = Runtime_Access_Result::ok;
|
|
|
|
|
});
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
static Runtime_Access_Result runtime_read_impl(const Property_Object_Base& base, detail::Access_Kind mode, std::string_view key, void* context, Runtime_Read_Callback callback) {
|
|
|
|
|
static Runtime_Access_Result runtime_read_impl(const Property_Object_Base& base, std::string_view key, void* context, Runtime_Read_Callback callback) {
|
|
|
|
|
const auto& self = static_cast<const Property_Object&>(base);
|
|
|
|
|
switch (mode) {
|
|
|
|
|
case detail::Access_Kind::intrinsic:
|
|
|
|
|
return self.template runtime_read_mode<detail::Access_Kind::intrinsic>(key, context, callback);
|
|
|
|
|
case detail::Access_Kind::external:
|
|
|
|
|
return self.template runtime_read_mode<detail::Access_Kind::external>(key, context, callback);
|
|
|
|
|
case detail::Access_Kind::persistence:
|
|
|
|
|
return self.template runtime_read_mode<detail::Access_Kind::persistence>(key, context, callback);
|
|
|
|
|
}
|
|
|
|
|
return Runtime_Access_Result::not_readable;
|
|
|
|
|
return self.runtime_read_impl_local(key, context, callback);
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Runtime_Access_Result runtime_write_mode(std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
Runtime_Access_Result runtime_write_impl_local(std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
auto index = schema_property_index<Schema>(key);
|
|
|
|
|
if (!index) {
|
|
|
|
|
return Runtime_Access_Result::unknown_property;
|
|
|
|
|
}
|
|
|
|
|
if (!runtime_property_visible<Mode>(*index)) {
|
|
|
|
|
if (!runtime_property_writable(*index)) {
|
|
|
|
|
return Runtime_Access_Result::not_writable;
|
|
|
|
|
}
|
|
|
|
|
Runtime_Access_Result result = Runtime_Access_Result::unknown_property;
|
|
|
|
@@ -761,28 +732,20 @@ private:
|
|
|
|
|
using Property = typename Schema::template property_type<property_index>;
|
|
|
|
|
using Accessor = typename Property::accessor_type;
|
|
|
|
|
using Value = typename Property::value_type;
|
|
|
|
|
if constexpr (!detail::property_write_allowed_v<Mode, Schema, property_index> || !requires(const Accessor& accessor, Derived& object, const Value& candidate) { accessor.write(object, candidate); }) {
|
|
|
|
|
if constexpr (!Schema::template property_type<property_index>::writable || !requires(const Accessor& accessor, Derived& object, const Value& candidate) { accessor.write(object, candidate); }) {
|
|
|
|
|
result = Runtime_Access_Result::not_writable;
|
|
|
|
|
} else if (value_type != typeid(Value)) {
|
|
|
|
|
result = Runtime_Access_Result::type_mismatch;
|
|
|
|
|
} else {
|
|
|
|
|
write_one<Mode, property_index>(*static_cast<const Value*>(value));
|
|
|
|
|
write_one<property_index>(*static_cast<const Value*>(value));
|
|
|
|
|
result = Runtime_Access_Result::ok;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
static Runtime_Access_Result runtime_write_impl(Property_Object_Base& base, detail::Access_Kind mode, std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
static Runtime_Access_Result runtime_write_impl(Property_Object_Base& base, std::string_view key, const std::type_info& value_type, const void* value) {
|
|
|
|
|
auto& self = static_cast<Property_Object&>(base);
|
|
|
|
|
switch (mode) {
|
|
|
|
|
case detail::Access_Kind::intrinsic:
|
|
|
|
|
return self.template runtime_write_mode<detail::Access_Kind::intrinsic>(key, value_type, value);
|
|
|
|
|
case detail::Access_Kind::external:
|
|
|
|
|
return self.template runtime_write_mode<detail::Access_Kind::external>(key, value_type, value);
|
|
|
|
|
case detail::Access_Kind::persistence:
|
|
|
|
|
return self.template runtime_write_mode<detail::Access_Kind::persistence>(key, value_type, value);
|
|
|
|
|
}
|
|
|
|
|
return Runtime_Access_Result::not_writable;
|
|
|
|
|
return self.runtime_write_impl_local(key, value_type, value);
|
|
|
|
|
}
|
|
|
|
|
static const Property_Object_Base::Runtime_Interface* runtime_interface() noexcept {
|
|
|
|
|
static const Property_Object_Base::Runtime_Interface value{
|
|
|
|
@@ -830,32 +793,32 @@ public:
|
|
|
|
|
return static_cast<const Derived&>(*this);
|
|
|
|
|
}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
auto read() const {
|
|
|
|
|
auto read() const requires Schema_Readable_Property_Member<type_descriptor_schema_t<Derived>, Member> {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return read_one<detail::Access_Kind::intrinsic, index>();
|
|
|
|
|
return read_one<index>();
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key>
|
|
|
|
|
auto read_key() const {
|
|
|
|
|
auto read_key() const requires Schema_Readable_Property_Key<type_descriptor_schema_t<Derived>, Key> {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return read_one<detail::Access_Kind::intrinsic, index>();
|
|
|
|
|
return read_one<index>();
|
|
|
|
|
}
|
|
|
|
|
template <auto Member, class Value>
|
|
|
|
|
void write(Value&& value) {
|
|
|
|
|
void write(Value&& value) requires Schema_Writable_Property_Member<type_descriptor_schema_t<Derived>, Member> {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
write_one<detail::Access_Kind::intrinsic, index>(std::forward<Value>(value));
|
|
|
|
|
write_one<index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key, class Value>
|
|
|
|
|
void write_key(Value&& value) {
|
|
|
|
|
void write_key(Value&& value) requires Schema_Writable_Property_Key<type_descriptor_schema_t<Derived>, Key> {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
write_one<detail::Access_Kind::intrinsic, index>(std::forward<Value>(value));
|
|
|
|
|
write_one<index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
std::size_t lock_slot() const noexcept {
|
|
|
|
@@ -865,209 +828,64 @@ public:
|
|
|
|
|
return slot(index);
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Basic_Read_Guard<Mode> lock_shared_mode(std::span<const std::string_view> keys) const {
|
|
|
|
|
return Basic_Read_Guard<Mode>{*this, collect_dynamic_lock_targets<Mode>(keys, true)};
|
|
|
|
|
Basic_Read_Guard lock_shared_impl(std::span<const std::string_view> keys) const {
|
|
|
|
|
return Basic_Read_Guard{*this, collect_dynamic_lock_targets(keys, true)};
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Basic_Read_Guard<Mode> lock_shared_mode(std::initializer_list<std::string_view> keys) const {
|
|
|
|
|
return lock_shared_mode<Mode>(std::span<const std::string_view>{keys.begin(), keys.size()});
|
|
|
|
|
Basic_Read_Guard lock_shared_impl(std::initializer_list<std::string_view> keys) const {
|
|
|
|
|
return lock_shared_impl(std::span<const std::string_view>{keys.begin(), keys.size()});
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Basic_Write_Guard<Mode> lock_unique_mode(std::span<const std::string_view> keys) {
|
|
|
|
|
return Basic_Write_Guard<Mode>{*this, collect_dynamic_lock_targets<Mode>(keys, false)};
|
|
|
|
|
Basic_Write_Guard lock_unique_impl(std::span<const std::string_view> keys) {
|
|
|
|
|
return Basic_Write_Guard{*this, collect_dynamic_lock_targets(keys, false)};
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode>
|
|
|
|
|
Basic_Write_Guard<Mode> lock_unique_mode(std::initializer_list<std::string_view> keys) {
|
|
|
|
|
return lock_unique_mode<Mode>(std::span<const std::string_view>{keys.begin(), keys.size()});
|
|
|
|
|
Basic_Write_Guard lock_unique_impl(std::initializer_list<std::string_view> keys) {
|
|
|
|
|
return lock_unique_impl(std::span<const std::string_view>{keys.begin(), keys.size()});
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, auto... Members>
|
|
|
|
|
auto lock_shared_mode() const {
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_shared_impl() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert((Schema_Property_Member<Schema, Members> && ...));
|
|
|
|
|
auto targets = collect_static_lock_targets<Mode, true, schema_member_property_index_v<Schema, Members>...>();
|
|
|
|
|
return Static_Read_Guard<Mode, sizeof...(Members)>{*this, std::move(targets)};
|
|
|
|
|
auto targets = collect_static_lock_targets<true, schema_member_property_index_v<Schema, Members>...>();
|
|
|
|
|
return Static_Read_Guard<sizeof...(Members)>{*this, std::move(targets)};
|
|
|
|
|
}
|
|
|
|
|
template <detail::Access_Kind Mode, auto... Members>
|
|
|
|
|
auto lock_unique_mode() {
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_unique_impl() {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
static_assert((Schema_Property_Member<Schema, Members> && ...));
|
|
|
|
|
auto targets = collect_static_lock_targets<Mode, false, schema_member_property_index_v<Schema, Members>...>();
|
|
|
|
|
return Static_Write_Guard<Mode, sizeof...(Members)>{*this, std::move(targets)};
|
|
|
|
|
auto targets = collect_static_lock_targets<false, schema_member_property_index_v<Schema, Members>...>();
|
|
|
|
|
return Static_Write_Guard<sizeof...(Members)>{*this, std::move(targets)};
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
Intrinsic_Read_Guard lock_shared(std::span<const std::string_view> keys) const {
|
|
|
|
|
return lock_shared_mode<detail::Access_Kind::intrinsic>(keys);
|
|
|
|
|
Read_Guard lock_shared(std::span<const std::string_view> keys) const {
|
|
|
|
|
return lock_shared_impl(keys);
|
|
|
|
|
}
|
|
|
|
|
Intrinsic_Read_Guard lock_shared(std::initializer_list<std::string_view> keys) const {
|
|
|
|
|
return lock_shared_mode<detail::Access_Kind::intrinsic>(keys);
|
|
|
|
|
Read_Guard lock_shared(std::initializer_list<std::string_view> keys) const {
|
|
|
|
|
return lock_shared_impl(keys);
|
|
|
|
|
}
|
|
|
|
|
Intrinsic_Write_Guard lock_unique(std::span<const std::string_view> keys) {
|
|
|
|
|
return lock_unique_mode<detail::Access_Kind::intrinsic>(keys);
|
|
|
|
|
Write_Guard lock_unique(std::span<const std::string_view> keys) {
|
|
|
|
|
return lock_unique_impl(keys);
|
|
|
|
|
}
|
|
|
|
|
Intrinsic_Write_Guard lock_unique(std::initializer_list<std::string_view> keys) {
|
|
|
|
|
return lock_unique_mode<detail::Access_Kind::intrinsic>(keys);
|
|
|
|
|
Write_Guard lock_unique(std::initializer_list<std::string_view> keys) {
|
|
|
|
|
return lock_unique_impl(keys);
|
|
|
|
|
}
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_shared() const {
|
|
|
|
|
return lock_shared_mode<detail::Access_Kind::intrinsic, Members...>();
|
|
|
|
|
auto lock_shared() const requires (Schema_Readable_Property_Member<type_descriptor_schema_t<Derived>, Members> && ...) {
|
|
|
|
|
return lock_shared_impl<Members...>();
|
|
|
|
|
}
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_unique() {
|
|
|
|
|
return lock_unique_mode<detail::Access_Kind::intrinsic, Members...>();
|
|
|
|
|
auto lock_unique() requires (Schema_Writable_Property_Member<type_descriptor_schema_t<Derived>, Members> && ...) {
|
|
|
|
|
return lock_unique_impl<Members...>();
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable(Function&& function) const {
|
|
|
|
|
for_each_readable_impl<detail::Access_Kind::intrinsic>(std::forward<Function>(function));
|
|
|
|
|
for_each_readable_impl(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable_locked(Function&& function) const {
|
|
|
|
|
for_each_readable_locked_impl<detail::Access_Kind::intrinsic>(std::forward<Function>(function));
|
|
|
|
|
for_each_readable_locked_impl(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void with_all_writable_locked(Function&& function) {
|
|
|
|
|
with_all_writable_locked_impl<detail::Access_Kind::intrinsic>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <Managed_Access_Mode Mode>
|
|
|
|
|
class Capability_View {
|
|
|
|
|
Property_Object* owner_{};
|
|
|
|
|
public:
|
|
|
|
|
explicit Capability_View(Property_Object& owner) : owner_(&owner) {}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
auto read() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return owner_->template read_one<detail::access_kind_v<Mode>, index>();
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key>
|
|
|
|
|
auto read_key() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return owner_->template read_one<detail::access_kind_v<Mode>, index>();
|
|
|
|
|
}
|
|
|
|
|
template <auto Member, class Value>
|
|
|
|
|
void write(Value&& value) requires (Mode != Managed_Access_Mode::persistence) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
owner_->template write_one<detail::access_kind_v<Mode>, index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key, class Value>
|
|
|
|
|
void write_key(Value&& value) requires (Mode != Managed_Access_Mode::persistence) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
owner_->template write_one<detail::access_kind_v<Mode>, index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <auto Member, class Value>
|
|
|
|
|
void load(Value&& value) requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
owner_->template write_one<detail::access_kind_v<Mode>, index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key, class Value>
|
|
|
|
|
void load_key(Value&& value) requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
owner_->template write_one<detail::access_kind_v<Mode>, index>(std::forward<Value>(value));
|
|
|
|
|
}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
auto store() const requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
return read<Member>();
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key>
|
|
|
|
|
auto store_key() const requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
return read_key<Key>();
|
|
|
|
|
}
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_shared() const {
|
|
|
|
|
return owner_->template lock_shared_mode<detail::access_kind_v<Mode>, Members...>();
|
|
|
|
|
}
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_unique() {
|
|
|
|
|
return owner_->template lock_unique_mode<detail::access_kind_v<Mode>, Members...>();
|
|
|
|
|
}
|
|
|
|
|
Read_Guard<Mode> lock_shared(std::span<const std::string_view> keys) const {
|
|
|
|
|
return owner_->template lock_shared_mode<detail::access_kind_v<Mode>>(keys);
|
|
|
|
|
}
|
|
|
|
|
Write_Guard<Mode> lock_unique(std::span<const std::string_view> keys) {
|
|
|
|
|
return owner_->template lock_unique_mode<detail::access_kind_v<Mode>>(keys);
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable(Function&& function) const {
|
|
|
|
|
owner_->template for_each_readable_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable_locked(Function&& function) const {
|
|
|
|
|
owner_->template for_each_readable_locked_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void with_all_writable_locked(Function&& function) requires (Mode != Managed_Access_Mode::persistence) {
|
|
|
|
|
owner_->template with_all_writable_locked_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void with_all_loadable_locked(Function&& function) requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
owner_->template with_all_writable_locked_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
template <Managed_Access_Mode Mode>
|
|
|
|
|
class Const_Capability_View {
|
|
|
|
|
const Property_Object* owner_{};
|
|
|
|
|
public:
|
|
|
|
|
explicit Const_Capability_View(const Property_Object& owner) : owner_(&owner) {}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
auto read() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_member_property_index_v<Schema, Member>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return owner_->template read_one<detail::access_kind_v<Mode>, index>();
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key>
|
|
|
|
|
auto read_key() const {
|
|
|
|
|
using Schema = type_descriptor_schema_t<Derived>;
|
|
|
|
|
constexpr auto index = schema_property_index_v<Schema, Key>;
|
|
|
|
|
static_assert(index < Schema::property_count);
|
|
|
|
|
return owner_->template read_one<detail::access_kind_v<Mode>, index>();
|
|
|
|
|
}
|
|
|
|
|
template <auto Member>
|
|
|
|
|
auto store() const requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
return read<Member>();
|
|
|
|
|
}
|
|
|
|
|
template <Fixed_String Key>
|
|
|
|
|
auto store_key() const requires (Mode == Managed_Access_Mode::persistence) {
|
|
|
|
|
return read_key<Key>();
|
|
|
|
|
}
|
|
|
|
|
template <auto... Members>
|
|
|
|
|
auto lock_shared() const {
|
|
|
|
|
return owner_->template lock_shared_mode<detail::access_kind_v<Mode>, Members...>();
|
|
|
|
|
}
|
|
|
|
|
Read_Guard<Mode> lock_shared(std::span<const std::string_view> keys) const {
|
|
|
|
|
return owner_->template lock_shared_mode<detail::access_kind_v<Mode>>(keys);
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable(Function&& function) const {
|
|
|
|
|
owner_->template for_each_readable_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
template <class Function>
|
|
|
|
|
void for_each_readable_locked(Function&& function) const {
|
|
|
|
|
owner_->template for_each_readable_locked_impl<detail::access_kind_v<Mode>>(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
Capability_View<Managed_Access_Mode::external> external() {
|
|
|
|
|
return Capability_View<Managed_Access_Mode::external>{*this};
|
|
|
|
|
}
|
|
|
|
|
Capability_View<Managed_Access_Mode::persistence> persistence() {
|
|
|
|
|
return Capability_View<Managed_Access_Mode::persistence>{*this};
|
|
|
|
|
}
|
|
|
|
|
Const_Capability_View<Managed_Access_Mode::external> external() const {
|
|
|
|
|
return Const_Capability_View<Managed_Access_Mode::external>{*this};
|
|
|
|
|
}
|
|
|
|
|
Const_Capability_View<Managed_Access_Mode::persistence> persistence() const {
|
|
|
|
|
return Const_Capability_View<Managed_Access_Mode::persistence>{*this};
|
|
|
|
|
with_all_writable_locked_impl(std::forward<Function>(function));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|