更新
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "concurrent/base/Concurrent_Struct.hpp"
|
||||
#include "model/Model.hpp"
|
||||
#include "statistics/Sliding_Statistics.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace aethera {
|
||||
/* 所有帧策略共享的自适应限速配置、公开状态和统计实现,不拥有具体调度状态。 */
|
||||
struct Frame_Policy : Model_Layer<
|
||||
@@ -16,7 +13,6 @@ struct Frame_Policy : Model_Layer<
|
||||
Storage_Registration<Prop_Tag, Import_Struct_With_Dirty>,
|
||||
Storage_Registration<State_Tag, Export_Struct>> {
|
||||
static constexpr double Default_Frames_Per_Second{30.0};
|
||||
|
||||
struct Prop : Prev<Prop_Tag> {
|
||||
std::optional<double> user_frames_per_second; /* 有值时作为用户帧率上限;无值时不参与限速。 */
|
||||
bool render_rate_limit_enabled{}; /* true 时用渲染平均耗时推导理论生成上限。 */
|
||||
@@ -39,5 +35,4 @@ struct Frame_Policy : Model_Layer<
|
||||
struct Builder : Prev_Builder {};
|
||||
};
|
||||
}
|
||||
|
||||
#include "Frame_Policy.ipp"
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace aethera {
|
||||
* 自适应限速、最多三帧在途的 latest-only 策略。Scene 创建三个具体帧;策略轮转复用,
|
||||
* 三槽均忙时丢弃本次 tick;stop completion 前排空 Scene/Sink 借用并销毁全部帧。
|
||||
*/
|
||||
struct Throttled_Latest_only :
|
||||
Def<Throttled_Latest_only, Frame_Policy> {
|
||||
struct Throttled_Latest_only : Def<Throttled_Latest_only, Frame_Policy> {
|
||||
enum struct Start_Result : std::uint8_t {
|
||||
started,
|
||||
already_running,
|
||||
|
||||
@@ -3,33 +3,60 @@
|
||||
#include "../concurrent/storage/Tagged_Storage.hpp"
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
namespace aethera {
|
||||
namespace detail {
|
||||
template <typename... Types> struct Model_Type_List {};
|
||||
template <typename List, typename... Registrations> struct Append_Model_Registrations;
|
||||
template <typename Tag, typename List> struct Model_Tag_Registered;
|
||||
template <typename Tag, typename Base, bool Registered> struct Previous_Model_Value;
|
||||
struct Empty_Prop {};
|
||||
struct Empty_State {};
|
||||
template <typename Tag, typename Layer, typename = void> struct Model_Tag_Value;
|
||||
template <typename Tag, typename List> struct Model_Registration;
|
||||
template <typename Tag, typename Layer, typename List> struct Model_Value;
|
||||
template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename Layer,
|
||||
typename... Args>
|
||||
concept Writable_Model_Value = requires(
|
||||
Concurrent_Storage<typename Model_Value<
|
||||
Tag,
|
||||
Layer,
|
||||
typename Layer::Storage_Registrations>::Type>& storage,
|
||||
Args&&... args) {
|
||||
storage.write(std::forward<Args>(args)...);
|
||||
};
|
||||
template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename Layer,
|
||||
typename... Args>
|
||||
concept Readable_Model_Value = requires(
|
||||
const Concurrent_Storage<typename Model_Value<
|
||||
Tag,
|
||||
Layer,
|
||||
typename Layer::Storage_Registrations>::Type>& storage,
|
||||
Args&&... args) {
|
||||
storage.read(std::forward<Args>(args)...);
|
||||
};
|
||||
struct Empty_Model_Value {};
|
||||
}
|
||||
/* Tag 负责选择各定义层的 Prop 类型;同一个 Tag 在注册表中只允许出现一次。 */
|
||||
struct Prop_Tag {
|
||||
using Root_Type = detail::Empty_Prop;
|
||||
template <typename Layer> using Value = typename Layer::Prop;
|
||||
};
|
||||
/* Tag 负责选择各定义层的 State 类型。 */
|
||||
struct State_Tag {
|
||||
using Root_Type = detail::Empty_State;
|
||||
template <typename Layer> using Value = typename Layer::State;
|
||||
};
|
||||
/* 把一个业务 Tag 注册到接受单个值类型的 Concurrent Storage 模板。 */
|
||||
template <typename Tag, template <typename...> typename Concurrent_Storage> struct Storage_Registration {
|
||||
template <
|
||||
typename Tag,
|
||||
template <typename...> typename Concurrent_Storage>
|
||||
struct Storage_Registration {
|
||||
using Tag_Type = Tag;
|
||||
template <typename Value> using Storage = Concurrent_Storage<Value>;
|
||||
template <typename Layer>
|
||||
using Value = typename detail::Model_Tag_Value<Tag, Layer>::Type;
|
||||
};
|
||||
struct Root {
|
||||
using Storage_Registrations = detail::Model_Type_List<>;
|
||||
template <typename Tag> using Prev = typename Tag::Root_Type;
|
||||
struct Private {};
|
||||
struct Builder {};
|
||||
};
|
||||
@@ -40,12 +67,10 @@ template <typename Base, typename... Registrations> struct Model_Layer : Base {
|
||||
using Storage_Registrations = typename detail::Append_Model_Registrations<
|
||||
typename Base::Storage_Registrations,
|
||||
Registrations...>::Type;
|
||||
template <typename Tag> using Prev = typename detail::Previous_Model_Value<
|
||||
template <typename Tag> using Prev = typename detail::Model_Value<
|
||||
Tag,
|
||||
Base,
|
||||
detail::Model_Tag_Registered<
|
||||
Tag,
|
||||
typename Base::Storage_Registrations>::value>::Type;
|
||||
Storage_Registrations>::Type;
|
||||
using Prev_Private = typename Base::Private;
|
||||
using Prev_Builder = typename Base::Builder;
|
||||
};
|
||||
@@ -61,31 +86,34 @@ template <typename Self, typename Base, typename... Registrations> struct Def :
|
||||
template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args> requires requires(
|
||||
Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.write(std::forward<Args>(args)...);
|
||||
}
|
||||
typename... Args>
|
||||
requires detail::Writable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
Builder& set(Args&&... args);
|
||||
std::unique_ptr<Self> ret; /* 构建期间唯一拥有尚未发布的对象。 */
|
||||
};
|
||||
template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args> requires requires(
|
||||
Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.write(std::forward<Args>(args)...);
|
||||
}
|
||||
typename... Args>
|
||||
requires detail::Writable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
Self& write(Args&&... args);
|
||||
template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args> requires requires(
|
||||
const Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.read(std::forward<Args>(args)...);
|
||||
}
|
||||
typename... Args>
|
||||
requires detail::Readable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
const Self& read(Args&&... args) const;
|
||||
template <typename... Args> explicit Def(Args&&... args);
|
||||
std::unique_ptr<Private> d; /* 唯一拥有最终 Private 和完整 Tagged Storage 集。 */
|
||||
|
||||
@@ -28,13 +28,18 @@ struct Append_Model_Registrations<
|
||||
using Type = Model_Type_List<Existing..., Registrations...>;
|
||||
};
|
||||
|
||||
template <typename Tag, typename List>
|
||||
struct Model_Tag_Registered;
|
||||
template <typename Tag, typename Layer, typename>
|
||||
struct Model_Tag_Value {
|
||||
using Type = Empty_Model_Value;
|
||||
};
|
||||
|
||||
template <typename Tag, typename... Registrations>
|
||||
struct Model_Tag_Registered<Tag, Model_Type_List<Registrations...>> :
|
||||
std::bool_constant<(
|
||||
std::same_as<Tag, typename Registrations::Tag_Type> || ...)> {};
|
||||
template <typename Tag, typename Layer>
|
||||
struct Model_Tag_Value<
|
||||
Tag,
|
||||
Layer,
|
||||
std::void_t<typename Tag::template Value<Layer>>> {
|
||||
using Type = typename Tag::template Value<Layer>;
|
||||
};
|
||||
|
||||
template <typename List>
|
||||
struct Unique_Model_Tags;
|
||||
@@ -50,23 +55,37 @@ struct Unique_Model_Tags<Model_Type_List<Registration, Rest...>> :
|
||||
typename Rest::Tag_Type> && ...) &&
|
||||
Unique_Model_Tags<Model_Type_List<Rest...>>::value> {};
|
||||
|
||||
template <typename Tag, typename Base, bool Registered>
|
||||
struct Previous_Model_Value;
|
||||
template <typename Tag, typename List>
|
||||
struct Model_Registration;
|
||||
|
||||
template <typename Tag, typename Base>
|
||||
struct Previous_Model_Value<Tag, Base, false> {
|
||||
using Type = typename Tag::Root_Type;
|
||||
template <typename Tag, typename Registration, typename... Rest>
|
||||
struct Model_Registration<
|
||||
Tag,
|
||||
Model_Type_List<Registration, Rest...>> :
|
||||
Model_Registration<Tag, Model_Type_List<Rest...>> {};
|
||||
|
||||
template <
|
||||
typename Tag,
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename... Rest>
|
||||
struct Model_Registration<
|
||||
Tag,
|
||||
Model_Type_List<
|
||||
Storage_Registration<Tag, Concurrent_Storage>,
|
||||
Rest...>> {
|
||||
using Type = Storage_Registration<Tag, Concurrent_Storage>;
|
||||
};
|
||||
|
||||
template <typename Tag, typename Base>
|
||||
struct Previous_Model_Value<Tag, Base, true> {
|
||||
using Type = typename Tag::template Value<Base>;
|
||||
template <typename Tag, typename Layer, typename List>
|
||||
struct Model_Value {
|
||||
using Registration = typename Model_Registration<Tag, List>::Type;
|
||||
using Type = typename Registration::template Value<Layer>;
|
||||
};
|
||||
|
||||
template <typename Self, typename Registration>
|
||||
struct Attached_Model_Storage {
|
||||
using Tag = typename Registration::Tag_Type;
|
||||
using Value = typename Tag::template Value<Self>;
|
||||
using Value = typename Registration::template Value<Self>;
|
||||
using Type = Tagged_Storage<
|
||||
Tag,
|
||||
typename Registration::template Storage<Value>>;
|
||||
@@ -115,15 +134,18 @@ template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args>
|
||||
requires requires(
|
||||
Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.write(std::forward<Args>(args)...);
|
||||
}
|
||||
requires detail::Writable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
typename Def<Self, Base, Registrations...>::Builder&
|
||||
Def<Self, Base, Registrations...>::Builder::set(Args&&... args) {
|
||||
auto& storage = ret->d->template get<Tag>();
|
||||
using Value = typename Tag::template Value<Self>;
|
||||
using Value = typename detail::Model_Value<
|
||||
Tag,
|
||||
Self,
|
||||
Storage_Registrations>::Type;
|
||||
static_assert(std::same_as<
|
||||
std::remove_cvref_t<decltype(storage)>,
|
||||
Concurrent_Storage<Value>>,
|
||||
@@ -147,14 +169,17 @@ template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args>
|
||||
requires requires(
|
||||
Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.write(std::forward<Args>(args)...);
|
||||
}
|
||||
requires detail::Writable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
Self& Def<Self, Base, Registrations...>::write(Args&&... args) {
|
||||
auto& storage = d->template get<Tag>();
|
||||
using Value = typename Tag::template Value<Self>;
|
||||
using Value = typename detail::Model_Value<
|
||||
Tag,
|
||||
Self,
|
||||
Storage_Registrations>::Type;
|
||||
static_assert(std::same_as<
|
||||
std::remove_cvref_t<decltype(storage)>,
|
||||
Concurrent_Storage<Value>>,
|
||||
@@ -168,14 +193,17 @@ template <
|
||||
template <typename...> typename Concurrent_Storage,
|
||||
typename Tag,
|
||||
typename... Args>
|
||||
requires requires(
|
||||
const Concurrent_Storage<typename Tag::template Value<Self>>& storage,
|
||||
Args&&... args) {
|
||||
storage.read(std::forward<Args>(args)...);
|
||||
}
|
||||
requires detail::Readable_Model_Value<
|
||||
Concurrent_Storage,
|
||||
Tag,
|
||||
Self,
|
||||
Args...>
|
||||
const Self& Def<Self, Base, Registrations...>::read(Args&&... args) const {
|
||||
const auto& storage = d->template get<Tag>();
|
||||
using Value = typename Tag::template Value<Self>;
|
||||
using Value = typename detail::Model_Value<
|
||||
Tag,
|
||||
Self,
|
||||
Storage_Registrations>::Type;
|
||||
static_assert(std::same_as<
|
||||
std::remove_cvref_t<decltype(storage)>,
|
||||
Concurrent_Storage<Value>>,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
| `Model.hpp/.ipp` | 按 Tag 组合定义链,并在最终 `Def` 挂接注册存储。 |
|
||||
| `../concurrent/` | Model 使用的并发存储机制;拥有独立设计文档。 |
|
||||
|
||||
`Model_Layer` 通过 `Storage_Registration<Tag, Concurrent_Storage>` 注册一条业务值链。每个定义层用 `Prev<Tag>` 取得前一层值类型并继承;最终 `Def::Private` 根据完整注册表只创建一次 `Tagged_Storage_Set`。同一 Tag 重复注册属于编译期错误。
|
||||
`Model_Layer` 通过 `Storage_Registration<Tag, Concurrent_Storage>` 注册一条业务值链。Tag 只定义如何从 Layer 选择对应业务类型;选择不到时,模型统一使用默认空类型。每个定义层用 `Prev<Tag>` 取得前一层值类型并继承;最终 `Def::Private` 根据完整注册表只创建一次 `Tagged_Storage_Set`。同一 Tag 重复注册属于编译期错误。
|
||||
|
||||
Builder 使用 `set<Concurrent_Storage, Tag>(...)`,最终模型使用 `write<Concurrent_Storage, Tag>(...)` 和 `read<Concurrent_Storage, Tag>(...)`。两个模板参数必须命中同一注册项,参数能力直接由对应并发存储的 `write/read(...)` 重载约束:Struct 可以整对象或按成员读写,List 保留自身批次语义。Builder 对 Struct 同时建立内部读面和外部写面且不产生 dirty;其他存储保留自身写入/消费语义。
|
||||
|
||||
|
||||
@@ -6,25 +6,27 @@
|
||||
#include <concepts>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
struct Number_List_Root : std::vector<int> {};
|
||||
|
||||
namespace model_test {
|
||||
struct Number_List_Tag {
|
||||
using Root_Type = Number_List_Root;
|
||||
template <typename Layer>
|
||||
using Value = typename Layer::Numbers;
|
||||
template <typename Layer> using Value = typename Layer::Numbers;
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
using model_test::Number_List_Tag;
|
||||
|
||||
struct Test_Model_Base : aethera::Model_Layer<
|
||||
aethera::Root,
|
||||
aethera::Storage_Registration<
|
||||
aethera::Prop_Tag,
|
||||
aethera::Import_Struct_With_Dirty>,
|
||||
aethera::Storage_Registration<Number_List_Tag, aethera::Import_List>> {
|
||||
aethera::Storage_Registration<
|
||||
Number_List_Tag,
|
||||
aethera::Import_List>> {
|
||||
struct Prop : Prev<aethera::Prop_Tag> {
|
||||
int base_number{};
|
||||
};
|
||||
struct Numbers : Prev<Number_List_Tag> {};
|
||||
struct Numbers : Prev<Number_List_Tag>, std::vector<int> {};
|
||||
struct Private : Prev_Private {};
|
||||
struct Builder : Prev_Builder {};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user