3D改完
This commit is contained in:
@@ -8,6 +8,18 @@
|
||||
#include <optional>
|
||||
#include <proxy/proxy.h>
|
||||
namespace aethera {
|
||||
namespace detail {
|
||||
template <typename Tag, typename Endpoint, typename = void>
|
||||
struct Dag_Node_Facade {
|
||||
using Type = Tag;
|
||||
};
|
||||
|
||||
template <typename Tag, typename Endpoint>
|
||||
struct Dag_Node_Facade<Tag, Endpoint, std::void_t<typename Tag::template Relation_Node_Facade<Endpoint>>> {
|
||||
using Type = typename Tag::template Relation_Node_Facade<Endpoint>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
struct Dag_Node_Id {
|
||||
std::uint64_t value{}; /* 一张 DAG 内的稳定节点标识;0 表示未分配。 */
|
||||
};
|
||||
@@ -25,6 +37,7 @@ enum struct Dag_Result : std::uint8_t {
|
||||
/* 拥有节点 proxy 和实例级依赖边的完整 DAG 定义;proxy 的实际持有对象由使用方决定。 */
|
||||
template <typename Node_Facade>
|
||||
struct Dag_Relation {
|
||||
using Node = Node_Facade;
|
||||
struct Builder;
|
||||
struct Editor;
|
||||
Dag_Relation();
|
||||
@@ -82,8 +95,8 @@ struct Dag_Relation<Node_Facade>::Editor {
|
||||
/* Model 可注册的拥有型 DAG 关系;内部 commit 在所有者安全点验证并提交待处理事务。 */
|
||||
template <typename Node_Facade>
|
||||
struct Owned_Dag_Relation : detail::Relation_Definition<Owned_Dag_Relation<Node_Facade>, Node_Facade> {
|
||||
template <typename, typename Tag>
|
||||
using Attachment = Owned_Dag_Relation<Tag>;
|
||||
template <typename Endpoint, typename Tag>
|
||||
using Attachment = Owned_Dag_Relation<typename detail::Dag_Node_Facade<Tag, Endpoint>::Type>;
|
||||
using Graph = Dag_Relation<Node_Facade>;
|
||||
using Edit = std::move_only_function<void(typename Graph::Editor&)>;
|
||||
using Edit_Completion = std::move_only_function<void(std::expected<void, Dag_Result>)>;
|
||||
|
||||
@@ -24,6 +24,6 @@ Model 的可组合能力统一分为两层:
|
||||
|
||||
## 关系附件契约
|
||||
|
||||
关系附件必须提供权威 `Graph`、事务 `Edit`、事务完成回调,以及内部 `relation()`、`commit()`、`build(...)`。`Owned_Dag_Relation<Node_Facade>` 自身是一段式定义和实际附件,向最终 endpoint 选择性附加实体 `edit<Tag>`、Builder `relation<Tag>` 和 Private `relation<Tag>/commit<Tag>`。
|
||||
关系附件必须提供权威 `Graph`、事务 `Edit`、事务完成回调,以及内部 `relation()`、`commit()`、`build(...)`。`Owned_Dag_Relation<Tag>` 自身是一段式定义和实际附件,向最终 endpoint 选择性附加实体 `edit<Tag>`、Builder `relation<Tag>` 和 Private `relation<Tag>/commit<Tag>`。Tag 默认同时是节点 facade;Tag 可以用 `Relation_Node_Facade<Endpoint>` 为最终 endpoint 选择更窄的依赖 facade,但关系仍由原 Tag 唯一标识,禁止派生层再注册第二张同语义关系图。
|
||||
|
||||
`Dag_Relation::Builder` 在构建期验证完整关系;`Dag_Relation::Editor` 只记录单次事务命令;`Owned_Dag_Relation` 由关系所有者在安全点验证并提交。编辑 completion 在调用 `commit()` 的内部线程执行,不是跨线程异常传播边界。
|
||||
|
||||
@@ -32,6 +32,6 @@ Root 的类型擦除 state 操作表保存一份 Private 与附件解析器,De
|
||||
分别承载独占、共享和非拥有生命周期,同时把 proxy 解引用目标映射到 Model 的唯一 Private;实体公开类不实现 facade 值转发。
|
||||
|
||||
具体类型自身就是一段式附件定义。例如,并发结构使用 `Import_Struct_Concurrent<Tags...>`,拥有型 DAG 使用
|
||||
`Owned_Dag_Relation<Node_Facade>`。业务定义不再套额外的二段式注册包装。一个并发定义可连续绑定多个
|
||||
`Owned_Dag_Relation<Tag>`。Tag 默认也作为节点 facade;如果 Tag 定义 `Relation_Node_Facade<Endpoint>`,则最终 endpoint 只物化一份关系状态,并按最终类型选择节点 facade。业务定义不再套额外的二段式注册包装。一个并发定义可连续绑定多个
|
||||
Tag;它继承 `Concurrent_Definition<Self, Tags...>`,并在内部直接定义最终 endpoint 所物化的 `Attachment<Endpoint, Tag>`。Builder
|
||||
和实体只写 Tag,例如 `set<Prop_Tag>(...)`;具体附件及其存储值由该定义和最终 endpoint 唯一确定。
|
||||
|
||||
@@ -12,5 +12,8 @@ struct Renderable : facade_builder
|
||||
::add_convention<_event_routing_distance, std::optional<double>(const Event&) const noexcept>
|
||||
::add_convention<_dispatch_event, void(Event &)>
|
||||
::support_relocation<pro::constraint_level::nothrow>
|
||||
::build {};
|
||||
::build {
|
||||
template <typename Endpoint>
|
||||
using Relation_Node_Facade = typename Endpoint::Scene_Renderable_Facade;
|
||||
};
|
||||
} // namespace aethera::scene
|
||||
|
||||
@@ -62,7 +62,6 @@ void Scene::Private::advance_renderables() {
|
||||
renderable->advance();
|
||||
});
|
||||
}
|
||||
|
||||
scene::Submit_Event_Result Scene::Private::submit_event(std::unique_ptr<Event> event) {
|
||||
if (!event) return scene::Submit_Event_Result::event_missing;
|
||||
event_collector.submit(std::move(event));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace aethera {
|
||||
/* Scene 通过 Tag + Owned_Dag_Relation 在类型系统中表达其对 Renderable DAG 的唯一所有权。 */
|
||||
struct Scene : Def<Scene, Root, Owned_Dag_Relation<scene::Renderable>> {
|
||||
using Scene_Renderable_Facade = scene::Renderable;
|
||||
struct Private;
|
||||
Scene();
|
||||
~Scene() noexcept;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "model/attachment/dag/Dag_Relation.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
namespace {
|
||||
struct Test_Relation_Node : aethera::facade_builder
|
||||
::support_relocation<pro::constraint_level::nothrow>
|
||||
@@ -9,6 +10,23 @@ struct Test_Relation_Node : aethera::facade_builder
|
||||
struct Test_Relation_Model : aethera::Def<Test_Relation_Model, aethera::Root, aethera::Owned_Dag_Relation<Test_Relation_Node>> {
|
||||
struct Private : Prev_Private {};
|
||||
};
|
||||
struct Test_Adaptive_Relation_Tag : aethera::facade_builder
|
||||
::support_relocation<pro::constraint_level::nothrow>
|
||||
::build {
|
||||
template <typename Endpoint>
|
||||
using Relation_Node_Facade = typename Endpoint::Selected_Relation_Node_Facade;
|
||||
};
|
||||
struct Test_Narrow_Relation_Node : aethera::facade_builder
|
||||
::support_relocation<pro::constraint_level::nothrow>
|
||||
::build {};
|
||||
struct Test_Adaptive_Relation_Base : aethera::Def<Test_Adaptive_Relation_Base, aethera::Root, aethera::Owned_Dag_Relation<Test_Adaptive_Relation_Tag>> {
|
||||
using Selected_Relation_Node_Facade = Test_Adaptive_Relation_Tag;
|
||||
struct Private : Prev_Private {};
|
||||
};
|
||||
struct Test_Adaptive_Relation_Model : aethera::Def<Test_Adaptive_Relation_Model, Test_Adaptive_Relation_Base> {
|
||||
using Selected_Relation_Node_Facade = Test_Narrow_Relation_Node;
|
||||
struct Private : Prev_Private {};
|
||||
};
|
||||
template <typename Model>
|
||||
concept Exposes_Concurrent_Model_API = requires(Model& model) { model.template set<Test_Relation_Node>(0); };
|
||||
template <typename Builder>
|
||||
@@ -19,6 +37,7 @@ static_assert(std::same_as<aethera::detail::Materialized_Model_Attachment<Test_R
|
||||
static_assert(aethera::detail::Relation_Model_Tag<Test_Relation_Node, Test_Relation_Model>);
|
||||
static_assert(!Exposes_Concurrent_Model_API<Test_Relation_Model>);
|
||||
static_assert(!Exposes_Concurrent_Builder_API<Test_Relation_Model::Builder>);
|
||||
static_assert(std::same_as<aethera::detail::Materialized_Model_Attachment<Test_Adaptive_Relation_Tag, Test_Adaptive_Relation_Model>, aethera::Owned_Dag_Relation<Test_Narrow_Relation_Node>>);
|
||||
TEST(Dag_Relation, Registration_Composes_Only_Relation_APIs) {
|
||||
bool initialized{};
|
||||
Test_Relation_Model::Builder builder;
|
||||
@@ -42,4 +61,16 @@ TEST(Dag_Relation, Registration_Composes_Only_Relation_APIs) {
|
||||
aethera::detail::model_private(*model).relation<Test_Relation_Node>().for_each_topological([&](auto, auto&) { ++nodes; });
|
||||
EXPECT_EQ(nodes, 0);
|
||||
}
|
||||
TEST(Dag_Relation, Inherited_Tag_Selects_Final_Endpoint_Node_Facade_Without_Second_Relation) {
|
||||
bool selected{};
|
||||
Test_Adaptive_Relation_Model::Builder builder;
|
||||
builder
|
||||
.relation<Test_Adaptive_Relation_Tag>([&](auto& relation) {
|
||||
static_assert(std::same_as<typename std::remove_reference_t<decltype(relation)>::Node, Test_Narrow_Relation_Node>);
|
||||
selected = true;
|
||||
});
|
||||
auto model = builder.build();
|
||||
EXPECT_TRUE(model);
|
||||
EXPECT_TRUE(selected);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
- 每个 Model 定义层的 `Prop`、`State` 等值类型必须定义在所属类内并继承 `Prev<Tag>`,使同一 Tag 的值结构沿 Model 层级形成继承链。
|
||||
- 每层统一使用 `Def<当前层, Base, Definitions...>`;中间类是普通类,不需要模板化,也不区分末尾层。
|
||||
- 一段式附件定义写在所属 `Def` 的模板参数上。并发结构直接使用 `Import_Struct_Concurrent<Tags...>` 等具体类型,关系结构直接使用 `Owned_Dag_Relation<Node_Facade>`。
|
||||
- 一段式附件定义写在所属 `Def` 的模板参数上。并发结构直接使用 `Import_Struct_Concurrent<Tags...>` 等具体类型,关系结构直接使用 `Owned_Dag_Relation<Tag>`。Tag 默认同时是节点 facade;需要让派生 endpoint 使用模块专用 facade 时,由 Tag 的 `Relation_Node_Facade<Endpoint>` 选择实际节点 facade,派生层不得重复注册同一语义的关系状态。
|
||||
- 同一个注册组可以连续登记多个 Tag;相同 Tag 在完整继承链只能注册一次。
|
||||
- 每个具体附件类型同时声明 Tag、能力来源和实际 `Attachment<Endpoint, Tag>`。完整附件项链按 Builder 正在构建的最终 endpoint 求值,并由公共 `Root` 一次物化唯一的 `Private + Model_Attachment_Set`。
|
||||
- Builder 只拥有一个最终 endpoint 对象槽;被继承的 Def 层不得创建自己的 endpoint state、对象副本、附件或 Private 指针。Private 解析器只随 Root 的唯一类型擦除 state 保存一份,定义层通过零状态 `model_private(model)` 选择自身的类型化视图。
|
||||
|
||||
Reference in New Issue
Block a user