还是一堆bug的状态
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#include "Update_Completion.h"
|
||||
#include <algorithm>
|
||||
namespace renderive {
|
||||
namespace {
|
||||
std::atomic<Update_Id> next_update_id{1};
|
||||
int stage_index(Update_Stage stage) {
|
||||
switch (stage) {
|
||||
case Update_Stage::Input_Released:
|
||||
return 0;
|
||||
case Update_Stage::Committed:
|
||||
return 1;
|
||||
case Update_Stage::Rendered:
|
||||
return 2;
|
||||
case Update_Stage::Presented:
|
||||
return 3;
|
||||
}
|
||||
ASSERT(false, "Invalid Update_Stage");
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
Update_State::Stage_Record::Stage_Record(std::pmr::memory_resource* resource) : waiters(resource) {}
|
||||
Update_State::Update_State(Update_Id id) : update_id(id), input_released(memory_resource(Memory_Domain::Update_Completion)), committed(memory_resource(Memory_Domain::Update_Completion)), rendered(memory_resource(Memory_Domain::Update_Completion)), presented(memory_resource(Memory_Domain::Update_Completion)) {}
|
||||
Update_Id Update_State::id() const noexcept {
|
||||
return update_id;
|
||||
}
|
||||
bool Update_State::is_complete() const noexcept {
|
||||
return terminal.load(std::memory_order_acquire);
|
||||
}
|
||||
bool Update_State::stage_complete(Update_Stage stage) const noexcept {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
return slot(stage).completed;
|
||||
}
|
||||
Update_State::Stage_Record& Update_State::slot(Update_Stage stage) {
|
||||
switch (stage) {
|
||||
case Update_Stage::Input_Released:
|
||||
return input_released;
|
||||
case Update_Stage::Committed:
|
||||
return committed;
|
||||
case Update_Stage::Rendered:
|
||||
return rendered;
|
||||
case Update_Stage::Presented:
|
||||
return presented;
|
||||
}
|
||||
ASSERT(false, "Invalid Update_Stage");
|
||||
return presented;
|
||||
}
|
||||
const Update_State::Stage_Record& Update_State::slot(Update_Stage stage) const {
|
||||
return const_cast<Update_State*>(this)->slot(stage);
|
||||
}
|
||||
void Update_State::register_waiter(Update_Stage stage, Update_Waiter waiter) {
|
||||
std::error_code error;
|
||||
Update_Outcome outcome = Update_Outcome::Cancelled;
|
||||
bool ready = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
Stage_Record& record = slot(stage);
|
||||
if (record.completed) {
|
||||
error = record.error;
|
||||
outcome = record.outcome;
|
||||
ready = true;
|
||||
}
|
||||
else {
|
||||
record.waiters.push_back(std::move(waiter));
|
||||
}
|
||||
}
|
||||
if (ready)
|
||||
waiter.complete(error, outcome);
|
||||
}
|
||||
void Update_State::drain_completed_waiters(Stage_Record& record, std::pmr::vector<Update_Waiter>& waiters, std::error_code error, Update_Outcome outcome) {
|
||||
if (record.completed)
|
||||
return;
|
||||
record.completed = true;
|
||||
record.error = error;
|
||||
record.outcome = outcome;
|
||||
for (auto& waiter : record.waiters)
|
||||
waiters.push_back(std::move(waiter));
|
||||
record.waiters.clear();
|
||||
}
|
||||
void Update_State::complete_until(Update_Stage stage, std::error_code error, Update_Outcome outcome) {
|
||||
std::pmr::vector<Update_Waiter> waiters(memory_resource(Memory_Domain::Update_Completion));
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
int last = std::min(stage_index(stage), stage_index(Update_Stage::Presented));
|
||||
if (last >= stage_index(Update_Stage::Input_Released))
|
||||
drain_completed_waiters(input_released, waiters, error, outcome);
|
||||
if (last >= stage_index(Update_Stage::Committed))
|
||||
drain_completed_waiters(committed, waiters, error, outcome);
|
||||
if (last >= stage_index(Update_Stage::Rendered))
|
||||
drain_completed_waiters(rendered, waiters, error, outcome);
|
||||
if (last >= stage_index(Update_Stage::Presented)) {
|
||||
drain_completed_waiters(presented, waiters, error, outcome);
|
||||
terminal.store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
for (auto& waiter : waiters)
|
||||
waiter.complete(error, outcome);
|
||||
}
|
||||
void Update_State::complete_all(std::error_code error, Update_Outcome outcome) {
|
||||
complete_until(Update_Stage::Presented, error, outcome);
|
||||
}
|
||||
std::shared_ptr<Update_State> make_update_state() {
|
||||
std::pmr::polymorphic_allocator<Update_State> allocator(memory_resource(Memory_Domain::Update_Completion));
|
||||
return std::allocate_shared<Update_State>(allocator, next_update_id.fetch_add(1, std::memory_order_relaxed));
|
||||
}
|
||||
void complete_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& states, Update_Stage stage, std::error_code error, Update_Outcome outcome) {
|
||||
for (auto& state : states) {
|
||||
if (state)
|
||||
state->complete_until(stage, error, outcome);
|
||||
}
|
||||
states.clear();
|
||||
}
|
||||
void cancel_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& states) {
|
||||
for (auto& state : states) {
|
||||
if (state)
|
||||
state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled);
|
||||
}
|
||||
states.clear();
|
||||
}
|
||||
void supersede_update_states(std::pmr::vector<std::shared_ptr<Update_State>>& states) {
|
||||
for (auto& state : states) {
|
||||
if (state)
|
||||
state->complete_all({}, Update_Outcome::Superseded);
|
||||
}
|
||||
states.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user