完美一版
This commit is contained in:
@@ -1,17 +1,9 @@
|
||||
#include "scene.hpp" /* 后端共有 Prepare Scene 实现。 */
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
namespace aethera {
|
||||
Scene::Private::Event_Node::Event_Node(std::shared_ptr<Event> event_value) : event(std::move(event_value)) {}
|
||||
void Scene::Private::Event_Double_Buffer::destroy(Event_Node* node) noexcept {
|
||||
while (node) { Event_Node* next = node->next; delete node; node = next; }
|
||||
}
|
||||
Scene::Private::Event_Double_Buffer::~Event_Double_Buffer() {
|
||||
destroy(current); destroy(pending.exchange(nullptr, std::memory_order_acquire));
|
||||
}
|
||||
void Scene::Private::Event_Double_Buffer::push(std::shared_ptr<Event> event) {
|
||||
auto* node = new Event_Node(std::move(event));
|
||||
node->next = pending.load(std::memory_order_relaxed);
|
||||
while (!pending.compare_exchange_weak(node->next, node, std::memory_order_release, std::memory_order_relaxed)) {}
|
||||
void Scene::Private::Event_Queue::push(std::shared_ptr<Event> event) {
|
||||
if (!pending.enqueue(std::move(event))) throw std::bad_alloc{};
|
||||
}
|
||||
Scene::Private::Private() : runtime(std::make_unique<Runtime>()) {}
|
||||
Scene::Private::~Private() {
|
||||
@@ -19,6 +11,6 @@ Scene::Private::~Private() {
|
||||
}
|
||||
void Scene::Private::push_event(std::unique_ptr<Event> event) {
|
||||
if (!event) throw std::invalid_argument("scene event ownership must not be empty");
|
||||
event_buffer.push(std::shared_ptr<Event>{std::move(event)});
|
||||
event_queue.push(std::shared_ptr<Event>{std::move(event)});
|
||||
}
|
||||
}
|
||||
|
||||
+13
-26
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <concurrentqueue-1.0.5/concurrentqueue.h>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -8,25 +8,16 @@ namespace aethera {
|
||||
struct Scene::Private : Prev_Private {
|
||||
struct Result {}; /* process(...) 完成回调的结果类型;当前仅表示完成。 */
|
||||
struct Runtime; /* Scene 的 Taskflow 构建产物;完整定义位于本文件下方。 */
|
||||
/* 单生产批次节点只在外部入队与内部消费之间转移,不回收到待处理链。 */
|
||||
struct Event_Node {
|
||||
std::shared_ptr<Event> event; /* 原始事件对象的所有权;3D 异步提交成功后可延长到渲染域任务。 */
|
||||
Event_Node* next{}; /* 原子待处理栈或内部当前批次中的下一节点。 */
|
||||
explicit Event_Node(std::shared_ptr<Event> event_value);
|
||||
};
|
||||
/* Scene 唯一事件流:多生产者无锁压入 pending,Prepare 开始时原子交换为单消费者 current。 */
|
||||
struct Event_Double_Buffer : Pinned {
|
||||
std::atomic<Event_Node*> pending{}; /* 外部线程并发提交的待处理事件栈。 */
|
||||
Event_Node* current{}; /* Scene 执行线程独占、已恢复 FIFO 的当前批次。 */
|
||||
~Event_Double_Buffer();
|
||||
/* Scene 唯一事件流:第三方 MPMC 队列负责跨线程所有权转移,当前事件仅供单消费者重试。 */
|
||||
struct Event_Queue : Pinned {
|
||||
moodycamel::ConcurrentQueue<std::shared_ptr<Event>> pending{}; /* 外部线程提交、Prepare 线程消费的事件队列。 */
|
||||
std::shared_ptr<Event> current{}; /* 后端暂不可用时留到下一帧重试的事件。 */
|
||||
void push(std::shared_ptr<Event> event);
|
||||
template <typename Callback>
|
||||
void consume(Callback&& callback) requires std::predicate<Callback, const std::shared_ptr<Event>&>;
|
||||
private:
|
||||
static void destroy(Event_Node* node) noexcept;
|
||||
};
|
||||
std::unique_ptr<Runtime> runtime; /* Scene 唯一运行时构建产物的所有权。 */
|
||||
Event_Double_Buffer event_buffer; /* 跨输入线程与 Scene Prepare 边界交换的唯一事件队列。 */
|
||||
Event_Queue event_queue; /* 跨输入线程与 Scene Prepare 边界交换的唯一事件队列。 */
|
||||
Private();
|
||||
~Private();
|
||||
/* 将事件所有权无锁提交到外部待处理批次;空所有权违反调用契约。 */
|
||||
@@ -53,21 +44,17 @@ struct Scene::Private::Runtime {
|
||||
std::unique_ptr<tf::Taskflow> taskflow; /* 当前已构建的总 Taskflow;为空表示尚未构建。 */
|
||||
};
|
||||
template <typename Callback>
|
||||
void Scene::Private::Event_Double_Buffer::consume(Callback&& callback) requires std::predicate<Callback, const std::shared_ptr<Event>&> {
|
||||
if (!current) {
|
||||
Event_Node* incoming = pending.exchange(nullptr, std::memory_order_acquire);
|
||||
while (incoming) {
|
||||
Event_Node* next = incoming->next; incoming->next = current; current = incoming; incoming = next;
|
||||
}
|
||||
}
|
||||
while (current) {
|
||||
if (!std::invoke(callback, std::as_const(current->event))) return;
|
||||
std::unique_ptr<Event_Node> node{current}; current = current->next;
|
||||
void Scene::Private::Event_Queue::consume(Callback&& callback) requires std::predicate<Callback, const std::shared_ptr<Event>&> {
|
||||
if (current && !std::invoke(callback, std::as_const(current))) return;
|
||||
current.reset();
|
||||
while (pending.try_dequeue(current)) {
|
||||
if (!std::invoke(callback, std::as_const(current))) return;
|
||||
current.reset();
|
||||
}
|
||||
}
|
||||
template <typename Callback>
|
||||
void Scene::Private::consume_events(Callback&& callback) requires std::predicate<Callback, const std::shared_ptr<Event>&> {
|
||||
event_buffer.consume(std::forward<Callback>(callback));
|
||||
event_queue.consume(std::forward<Callback>(callback));
|
||||
}
|
||||
template <Attached Object, typename Callback>
|
||||
void Scene::Private::process(Object* object, Callback&& callback) requires std::invocable<Callback, const Result&> {
|
||||
|
||||
Reference in New Issue
Block a user