架构优化

This commit is contained in:
2026-08-11 12:40:28 +08:00
parent e91f134f16
commit 8d4714f691
17 changed files with 210 additions and 107 deletions
+43 -22
View File
@@ -238,13 +238,7 @@ struct Schema_Dependency_Indices<Schema, Property_Dependencies<Dependencies...>>
template <Property_Schema Schema, std::size_t Index>
consteval auto schema_property_dependency_indices() requires Schema_Property_Index<Schema, Index> {
using dependency_spec = typename Schema::template property_type<Index>::dependency_spec;
constexpr auto indices = Schema_Dependency_Indices<Schema, dependency_spec>::value;
for (auto dependency : indices) {
if (dependency == Index) {
throw "computed property cannot depend on itself";
}
}
return indices;
return Schema_Dependency_Indices<Schema, dependency_spec>::value;
}
template <class Schema, std::size_t Index>
inline constexpr std::size_t schema_property_dependency_count_v = schema_property_dependency_indices<Schema, Index>().size();
@@ -271,6 +265,37 @@ consteval auto schema_property_dependency_matrix() {
}(std::make_index_sequence<Schema::property_count>{});
return matrix;
}
template <Property_Schema Schema>
consteval bool schema_dependency_graph_acyclic() {
constexpr auto dependencies = schema_property_dependency_matrix<Schema>();
std::array<std::size_t, Schema::property_count> dependency_counts{};
std::array<std::size_t, Schema::property_count> ready{};
std::size_t ready_begin = 0;
std::size_t ready_end = 0;
for (std::size_t property = 0; property < Schema::property_count; ++property) {
for (std::size_t dependency = 0; dependency < Schema::property_count; ++dependency) {
dependency_counts[property] += dependencies[property][dependency] ? 1u : 0u;
}
if (dependency_counts[property] == 0) {
ready[ready_end++] = property;
}
}
std::size_t resolved_count = 0;
while (ready_begin != ready_end) {
auto resolved = ready[ready_begin++];
++resolved_count;
for (std::size_t property = 0; property < Schema::property_count; ++property) {
if (!dependencies[property][resolved]) {
continue;
}
--dependency_counts[property];
if (dependency_counts[property] == 0) {
ready[ready_end++] = property;
}
}
}
return resolved_count == Schema::property_count;
}
template <class Schema, std::size_t Index, class Category, class Fallback>
struct Effective_Attribute {
private:
@@ -301,11 +326,11 @@ constexpr decltype(auto) declared_effective_attribute(const Schema& schema) requ
}
}
template <class Schema>
concept Valid_Property_Schema = Property_Schema<Schema>;
concept Valid_Property_Schema = Property_Schema<Schema> && schema_dependency_graph_acyclic<Schema>();
template <class Schema, std::size_t Index>
inline constexpr bool property_requires_synchronization_v = Schema::template property_type<Index>::writable || Schema::template property_type<Index>::synchronized_view_read;
template <class Schema, std::size_t Index>
inline constexpr bool property_has_derived_synchronization_v = Schema::template property_type<Index>::synchronized_view_read && !Schema::template property_type<Index>::writable && Schema::template property_type<Index>::declares_dependencies;
inline constexpr bool property_has_derived_synchronization_v = Schema::template property_type<Index>::synchronized_view_read && !Schema::template property_type<Index>::writable;
template <class Schema, std::size_t Index>
inline constexpr bool property_owns_synchronization_domain_v = Schema::template property_type<Index>::writable || (Schema::template property_type<Index>::synchronized_view_read && !property_has_derived_synchronization_v<Schema, Index>);
template <class Schema, std::size_t Index>
@@ -331,7 +356,6 @@ Resolved_Synchronization_Plan<Schema::property_count> resolve_synchronization_pl
return std::array<bool, Schema::property_count>{property_has_derived_synchronization_v<Schema, Index>...};
}(std::make_index_sequence<Schema::property_count>{});
constexpr auto dependencies = schema_property_dependency_matrix<Schema>();
constexpr auto keys = schema_property_keys<Schema>();
std::array<std::size_t, Schema::property_count> logical{};
std::array<bool, Schema::property_count> explicitly_configured{};
std::size_t next_token = Schema::property_count + 1;
@@ -407,18 +431,12 @@ Resolved_Synchronization_Plan<Schema::property_count> resolve_synchronization_pl
}
}
if constexpr (Schema::property_count > 0) {
std::array<unsigned char, Schema::property_count> dependency_state{};
constexpr auto keys = schema_property_keys<Schema>();
std::array<bool, Schema::property_count> dependency_resolved{};
auto resolve_derived_slot = [&](auto&& self, std::size_t index) -> std::size_t {
if (!derived_synchronization[index]) {
if (!derived_synchronization[index] || dependency_resolved[index]) {
return resolved.lock_slots[index];
}
if (dependency_state[index] == 2) {
return resolved.lock_slots[index];
}
if (dependency_state[index] == 1) {
throw std::invalid_argument("Computed property dependency cycle: " + std::string(keys[index]));
}
dependency_state[index] = 1;
bool has_dependency_domain = false;
std::size_t dependency_slot = unsynchronized_slot;
for (std::size_t dependency = 0; dependency < Schema::property_count; ++dependency) {
@@ -434,7 +452,7 @@ Resolved_Synchronization_Plan<Schema::property_count> resolve_synchronization_pl
}
}
resolved.lock_slots[index] = has_dependency_domain ? dependency_slot : unsynchronized_slot;
dependency_state[index] = 2;
dependency_resolved[index] = true;
return resolved.lock_slots[index];
};
for (std::size_t index = 0; index < Schema::property_count; ++index) {
@@ -512,10 +530,13 @@ bool visit_schema_property(const Schema& schema, std::string_view key_value, Fun
template <class Object, class Defaults, class Source, class... Properties>
auto make_object_schema(Defaults&& object_defaults, Source&& synchronization_source, Properties&&... properties) requires Synchronization_Source_Type<std::remove_cvref_t<Source>> {
using schema_type = Object_Schema<Object, std::decay_t<Defaults>, std::decay_t<Properties>...>;
static_assert(Valid_Property_Schema<schema_type>);
constexpr bool valid_schema = Valid_Property_Schema<schema_type>;
static_assert(valid_schema, "property dependency graph must be valid and acyclic");
auto plan = materialize_synchronization_plan<schema_type>(std::forward<Source>(synchronization_source));
schema_type schema{std::forward<Defaults>(object_defaults), std::move(plan), std::tuple<std::decay_t<Properties>...>{std::forward<Properties>(properties)...}};
static_cast<void>(resolve_synchronization_plan(schema, schema.synchronization_plan()));
if constexpr (valid_schema) {
static_cast<void>(resolve_synchronization_plan(schema, schema.synchronization_plan()));
}
return schema;
}
template <class Object, class Defaults, class Source, class... Properties>