载入中...
搜索中...
未找到
DefinitionRuntime.cpp
浏览该文件的文档.
2
3#include <exception>
4#include <utility>
5
6namespace eve::definition {
7namespace {
8
16class PayloadGuard {
17public:
18 PayloadGuard(void* payload, RuntimeInstanceCore::DestroyFunction destroy) noexcept
19 : payload_(payload), destroy_(destroy) {}
20 ~PayloadGuard() { reset(); }
21
22 PayloadGuard(const PayloadGuard&) = delete;
23 PayloadGuard& operator=(const PayloadGuard&) = delete;
24
26 void adopt(void* payload) noexcept {
27 reset();
28 payload_ = payload;
29 }
30
31 [[nodiscard]] void* get() const noexcept { return payload_; }
32
37 [[nodiscard]] void* release() noexcept {
38 void* payload = payload_;
39 payload_ = nullptr;
40 return payload;
41 }
42
44 void reset() noexcept {
45 if (payload_ != nullptr && destroy_ != nullptr) destroy_(payload_);
46 payload_ = nullptr;
47 }
48
49private:
50 void* payload_ = nullptr;
51 RuntimeInstanceCore::DestroyFunction destroy_ = nullptr;
52};
53
54} // namespace
55
57 AssignFunction assign, DestroyFunction destroy, bool active) noexcept
58 : identity_(std::move(identity)),
59 state_(state),
60 clone_(clone),
61 assign_(assign),
62 destroy_(destroy),
63 active_(active) {}
64
66 if (state_ != nullptr && destroy_ != nullptr) destroy_(state_);
67}
68
70 : identity_(other.identity_),
71 state_(other.clone_(other.state_)),
72 clone_(other.clone_),
73 assign_(other.assign_),
74 destroy_(other.destroy_),
75 active_(other.active_) {}
76
78 if (this == &other) return *this;
79 // Copy first: a throwing state copy must leave this instance untouched.
80 void* candidate = other.clone_(other.state_);
81 if (state_ != nullptr && destroy_ != nullptr) destroy_(state_);
82 identity_ = other.identity_;
83 state_ = candidate;
84 clone_ = other.clone_;
85 assign_ = other.assign_;
86 destroy_ = other.destroy_;
87 active_ = other.active_;
88 return *this;
89}
90
92 : identity_(std::move(other.identity_)),
93 state_(other.state_),
94 clone_(other.clone_),
95 assign_(other.assign_),
96 destroy_(other.destroy_),
97 active_(other.active_) {
98 other.state_ = nullptr;
99}
100
102 if (this == &other) return *this;
103 if (state_ != nullptr && destroy_ != nullptr) destroy_(state_);
104 identity_ = std::move(other.identity_);
105 state_ = other.state_;
106 clone_ = other.clone_;
107 assign_ = other.assign_;
108 destroy_ = other.destroy_;
109 active_ = other.active_;
110 other.state_ = nullptr;
111 return *this;
112}
113
115 if (!handle.isValid())
117 eve::DiagnosticCode::InvalidArgument, "definition handle is invalid", "handle", {}, "common.definitions"));
118 if (handle != identity_.definitionHandle())
120 eve::DiagnosticCode::StaleHandle, "runtime instance refers to a different definition generation", "handle",
121 {}, "common.definitions"));
123}
124
126 const void* defaults, const RebuildFunction& rebuild) {
127 if (!next.isValid())
129 "next definition handle is invalid", "next",
130 {}, "common.definitions"));
131 if (next.reference != identity_.definition)
133 eve::DiagnosticCode::Conflict, "definition reload targets a different logical definition", "next.reference",
134 {}, "common.definitions"));
135 if (next.generation < identity_.definitionGeneration)
137 eve::DiagnosticCode::StaleHandle, "definition reload handle is older than the instance generation",
138 "next.generation", {}, "common.definitions"));
139
140 ReloadOutcome outcome{
141 identity_.instanceId, identity_.definition, identity_.definitionGeneration, next.generation, policy,
143 if (next.generation == identity_.definitionGeneration)
145
146 if (policy == ReloadPolicy::RejectWhileActive && active_)
148 eve::Diagnostic::error(eve::DiagnosticCode::Conflict, "active runtime instance rejects definition reload",
149 "policy", {}, "common.definitions"));
150 if (policy == ReloadPolicy::ReapplyDefaults && (defaults == nullptr || assign_ == nullptr))
152 "reapply policy requires typed defaults",
153 "defaults", {}, "common.definitions"));
154
155 try {
156 PayloadGuard candidate(clone_(state_), destroy_);
158 if (policy == ReloadPolicy::ReapplyDefaults) {
159 assign_(candidate.get(), defaults);
161 } else if (policy == ReloadPolicy::RebuildInstance) {
162 if (!rebuild)
164 eve::DiagnosticCode::InvalidArgument, "rebuild policy requires a rebuild callback", "rebuild", {},
165 "common.definitions"));
166 auto rebuilt = rebuild(state_, identity_, next);
167 if (!rebuilt) return eve::Result<ReloadOutcome>::failure(rebuilt.status());
168 candidate.adopt(std::move(rebuilt).takeValue());
169 disposition = ReloadDisposition::Rebuilt;
170 } else if (policy == ReloadPolicy::RejectWhileActive) {
171 // The active guard was handled above. Inactive instances have
172 // the documented keep-values behavior.
173 disposition = ReloadDisposition::Kept;
174 }
175
176 if (state_ != nullptr && destroy_ != nullptr) destroy_(state_);
177 state_ = candidate.release();
178 identity_.definitionGeneration = next.generation;
179 outcome.disposition = disposition;
181 } catch (const std::exception&) {
183 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "definition reload candidate preparation failed", {},
184 {}, "common.definitions"));
185 } catch (...) {
187 eve::Diagnostic::error(eve::DiagnosticCode::Failed, "definition reload candidate preparation failed", {},
188 {}, "common.definitions"));
189 }
190}
191
193 PayloadGuard candidate(state, destroy_);
194 if (!identity.isValid())
196 "runtime snapshot identity is invalid", "identity", {},
197 "common.definitions"));
198 if (identity.instanceId != identity_.instanceId || identity.definition != identity_.definition)
200 eve::DiagnosticCode::Conflict, "runtime snapshot belongs to a different instance or definition", "identity",
201 {}, "common.definitions"));
204 eve::DiagnosticCode::StaleHandle, "runtime snapshot definition generation is not current",
205 "identity.definitionGeneration", {}, "common.definitions"));
206
207 if (state_ != nullptr && destroy_ != nullptr) destroy_(state_);
208 state_ = candidate.release();
209 active_ = active;
211}
212
213} // namespace eve::definition
Value::Object payload
bool & active
Common identity and hot-reload contract for typed runtime instances.
void(* destroy)(void *)
PrimitiveHandle handle
std::function< eve::Result< void >()> release
Definition Procgen.cpp:86
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Type-erased bookkeeping shared by every RuntimeInstance<State>.
~RuntimeInstanceCore()
Destroy the adopted payload.
std::function< eve::Result< void * >(const void *, const InstanceIdentity &, const DefinitionHandle &)> RebuildFunction
Type-erased rebuild policy callback.
void(*)(void *destination, const void *source) AssignFunction
Assigns one payload from another payload of the same state type.
eve::Result< ReloadOutcome > reload(const DefinitionHandle &next, ReloadPolicy policy, const void *defaults, const RebuildFunction &rebuild)
Apply a definition replacement with an atomic payload policy.
eve::Result< void > checkDefinition(const DefinitionHandle &handle) const
Verify that a caller's definition handle is the exact current incarnation.
void * state() noexcept
Borrow the payload; null only after a move.
eve::Result< void > restoreExact(const InstanceIdentity &identity, void *state, bool active)
Swap in an already validated payload of this exact instance.
RuntimeInstanceCore & operator=(const RuntimeInstanceCore &other)
Copy-assign; the copy is made before any mutation, so a throw leaves *this intact.
RuntimeInstanceCore(InstanceIdentity identity, void *state, CloneFunction clone, AssignFunction assign, DestroyFunction destroy, bool active) noexcept
Adopt an already-allocated payload.
void(*)(void *) noexcept DestroyFunction
Destroys one payload; must not throw.
const InstanceIdentity & identity() const noexcept
Borrow the complete immutable identity.
void *(*)(const void *) CloneFunction
Deep-copies one payload for the copy constructor and copy assignment.
ReloadPolicy
Policy used when a live definition is replaced.
@ RejectWhileActive
Reject the reload while the instance is active; inactive instances keep values.
@ ReapplyDefaults
Replace the typed state with defaults produced from the new definition.
@ RebuildInstance
Let the consumer atomically construct a new state from the new definition.
ReloadDisposition
Observable result of a successful or no-op definition reload.
A generation-qualified reference to one definition incarnation.
Canonical identity carried by every typed runtime instance.
bool isValid() const noexcept
Whether this identity has all required non-zero fields.
DefinitionHandle definitionHandle() const noexcept
Convert the logical reference and generation into a checked handle.
Identity transition emitted by a typed runtime reload operation.