Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
wrapper.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/assert.hpp>
6
7#include <cstddef>
8#include <functional>
9#include <string_view>
10
11namespace helios::ecs {
12
13/**
14 * @brief A wrapper around a message that provides convenient access to the
15 * message's data, type information, and the ability to mark the message as
16 * consumed.
17 * @details It holds a const reference to the underlying message, a reference to
18 * the `ConsumedMessagesRegistry`, and the global index of the message within
19 * the combined (previous + current) view.
20 *
21 * Marking a message as consumed writes into the per-system registry,
22 * which is later merged and applied at `MessageManager::Update` time.
23 *
24 * @note Thread-safe, except for the `Consume` method which is NOT thread-safe.
25 * @tparam T The type of the message being wrapped. Must satisfy
26 * `ConsumableMessageTrait`.
27 */
28template <ConsumableMessageTrait T>
30public:
31 /**
32 * @brief Constructs a `ConsumableMessageWrapper`.
33 * @details Intended to be called by `ConsumableMessageReader`; not part of
34 * the public construction API.
35 * @param message Const reference to the message
36 * @param registry Reference to the per-system consumed messages registry
37 * @param global_index Global index of the message in the combined (previous +
38 * current) view
39 */
40 constexpr ConsumableMessageWrapper(const T& message,
42 size_t global_index) noexcept
43 : message_(message), global_index_(global_index), registry_(registry) {}
44
46 default;
48 default;
49 constexpr ~ConsumableMessageWrapper() noexcept = default;
50
51 constexpr ConsumableMessageWrapper& operator=(
52 const ConsumableMessageWrapper&) noexcept = default;
53 constexpr ConsumableMessageWrapper& operator=(
54 ConsumableMessageWrapper&&) noexcept = default;
55
56 /**
57 * @brief Dereferences to the underlying message.
58 * @return A const reference to the underlying message data
59 */
60 [[nodiscard]] constexpr const T& operator*() const noexcept {
61 return message_.get();
62 }
63
64 /**
65 * @brief Provides member access to the underlying message.
66 * @return A pointer to the underlying message data
67 */
68 constexpr const T* operator->() const noexcept { return &message_.get(); }
69
70 /**
71 * @brief Marks the message as consumed.
72 * @details The message will not be propagated to subsequent frames after
73 * `MessageManager::Update` merges all per-system consumed registries.
74 * Multiple calls are idempotent (sorted-unique insertion).
75 */
76 constexpr void Consume() const {
77 registry_.get().template MarkConsumed<T>(global_index_);
78 }
79
80 /**
81 * @brief Checks whether this message has been marked as consumed by the
82 * owning system.
83 * @return True if the message has been consumed, false otherwise
84 */
85 [[nodiscard]] bool IsConsumed() const noexcept {
86 return registry_.get().template IsConsumed<T>(global_index_);
87 }
88
89 /**
90 * @brief Gets the name of the message type.
91 * @return A string view containing the name of the message type
92 */
93 [[nodiscard]] constexpr std::string_view Name() const noexcept {
94 return MessageNameOf<T>();
95 }
96
97 /**
98 * @brief Gets the type index of the message.
99 * @return A `MessageTypeIndex` representing the type index of the message
100 */
101 [[nodiscard]] constexpr MessageTypeIndex TypeIndex() const noexcept {
103 }
104
105 /**
106 * @brief Gets the global index of this message in the combined (previous +
107 * current) view.
108 * @return Global index
109 */
110 [[nodiscard]] constexpr size_t GlobalIndex() const noexcept {
111 return global_index_;
112 }
113
114 /**
115 * @brief Unwraps the message wrapper, returning a const reference to the
116 * underlying message.
117 * @return A const reference to the underlying message data
118 */
119 [[nodiscard]] constexpr const T& Unwrap() const noexcept {
120 return message_.get();
121 }
122
123private:
124 std::reference_wrapper<const T> message_; ///< Const reference to the message
125 size_t global_index_ = 0; ///< Global index in combined view
126 std::reference_wrapper<ConsumedMessagesRegistry<>>
127 registry_; ///< Per-system consumed registry
128};
129
130/**
131 * @brief A wrapper around a message that provides convenient access to the
132 * message's data and type information.
133 * @details It holds a const reference to the underlying message and the global
134 * index of the message within the combined (previous + current) view.
135 *
136 * Unlike `ConsumableMessageWrapper`, this wrapper does not provide message
137 * consumption functionality.
138 *
139 * @note Thread-safe.
140 * @tparam T The type of the message being wrapped. Must satisfy `MessageTrait`.
141 */
142template <MessageTrait T>
144public:
145 /**
146 * @brief Constructs a `MessageWrapper`.
147 * @details Intended to be called by `MessageReader`; not part of the public
148 * construction API.
149 * @param message Const reference to the message
150 * @param global_index Global index of the message in the combined (previous +
151 * current) view
152 */
153 constexpr MessageWrapper(const T& message, size_t global_index) noexcept
154 : message_(message), global_index_(global_index) {}
155
156 constexpr MessageWrapper(const MessageWrapper&) noexcept = default;
157 constexpr MessageWrapper(MessageWrapper&&) noexcept = default;
158 constexpr ~MessageWrapper() noexcept = default;
159
160 constexpr MessageWrapper& operator=(const MessageWrapper&) noexcept = default;
161 constexpr MessageWrapper& operator=(MessageWrapper&&) noexcept = default;
162
163 /**
164 * @brief Dereferences to the underlying message.
165 * @return A const reference to the underlying message data
166 */
167 [[nodiscard]] constexpr const T& operator*() const noexcept {
168 return message_.get();
169 }
170
171 /**
172 * @brief Provides member access to the underlying message.
173 * @return A pointer to the underlying message data
174 */
175 constexpr const T* operator->() const noexcept { return &message_.get(); }
176
177 /**
178 * @brief Gets the name of the message type.
179 * @return A string view containing the name of the message type
180 */
181 [[nodiscard]] constexpr std::string_view Name() const noexcept {
182 return MessageNameOf<T>();
183 }
184
185 /**
186 * @brief Gets the type index of the message.
187 * @return A `MessageTypeIndex` representing the type index of the message
188 */
189 [[nodiscard]] constexpr MessageTypeIndex TypeIndex() const noexcept {
191 }
192
193 /**
194 * @brief Gets the global index of this message in the combined (previous +
195 * current) view.
196 * @return Global index
197 */
198 [[nodiscard]] constexpr size_t GlobalIndex() const noexcept {
199 return global_index_;
200 }
201
202 /**
203 * @brief Unwraps the message wrapper, returning a const reference to the
204 * underlying message.
205 * @return A const reference to the underlying message data
206 */
207 [[nodiscard]] constexpr const T& Unwrap() const noexcept {
208 return message_.get();
209 }
210
211private:
212 std::reference_wrapper<const T> message_; ///< Const reference to the message
213 size_t global_index_ = 0; ///< Global index in combined view
214};
215
216} // namespace helios::ecs
constexpr const T & Unwrap() const noexcept
Unwraps the message wrapper, returning a const reference to the underlying message.
Definition wrapper.hpp:119
constexpr void Consume() const
Marks the message as consumed.
Definition wrapper.hpp:76
bool IsConsumed() const noexcept
Checks whether this message has been marked as consumed by the owning system.
Definition wrapper.hpp:85
constexpr std::string_view Name() const noexcept
Gets the name of the message type.
Definition wrapper.hpp:93
constexpr size_t GlobalIndex() const noexcept
Gets the global index of this message in the combined (previous + current) view.
Definition wrapper.hpp:110
constexpr ConsumableMessageWrapper(const T &message, ConsumedMessagesRegistry<> &registry, size_t global_index) noexcept
Constructs a ConsumableMessageWrapper.
Definition wrapper.hpp:40
constexpr ConsumableMessageWrapper(const ConsumableMessageWrapper &) noexcept=default
constexpr ConsumableMessageWrapper(ConsumableMessageWrapper &&) noexcept=default
constexpr const T * operator->() const noexcept
Provides member access to the underlying message.
Definition wrapper.hpp:68
constexpr MessageTypeIndex TypeIndex() const noexcept
Gets the type index of the message.
Definition wrapper.hpp:101
Per-system registry for tracking consumed message indices.
constexpr MessageWrapper(const T &message, size_t global_index) noexcept
Constructs a MessageWrapper.
Definition wrapper.hpp:153
constexpr std::string_view Name() const noexcept
Gets the name of the message type.
Definition wrapper.hpp:181
constexpr size_t GlobalIndex() const noexcept
Gets the global index of this message in the combined (previous + current) view.
Definition wrapper.hpp:198
constexpr const T & Unwrap() const noexcept
Unwraps the message wrapper, returning a const reference to the underlying message.
Definition wrapper.hpp:207
constexpr MessageWrapper(const MessageWrapper &) noexcept=default
constexpr MessageTypeIndex TypeIndex() const noexcept
Gets the type index of the message.
Definition wrapper.hpp:189
constexpr const T * operator->() const noexcept
Provides member access to the underlying message.
Definition wrapper.hpp:175
constexpr MessageWrapper(MessageWrapper &&) noexcept=default
static constexpr TypeIndex From() noexcept
Constructs a TypeIndex from a type T.
utils::TypeIndex MessageTypeIndex
Type index for messages.
Definition message.hpp:14
constexpr std::string_view MessageNameOf() noexcept
Gets the name of an message.
Definition message.hpp:97