#include "deimos/core/status.h" #include "deimos/core/api_registry.h" #include "deimos/core/allocator.h" #include "deimos/core/atomic.h" static deimos::AllocatorApi* allocator_api; namespace deimos { struct StatusRep { Atomic ref_count; StatusCode code{}; StringView message; }; Status::Status(StatusCode code, StringView message) { if (code == StatusCode::kOk) { m_rep = CodeToRep(StatusCode::kOk); } else { void* ptr = allocator_api->system->Allocate((int64_t)sizeof(StatusRep) + message.size() + 1); auto* rep = new(ptr) StatusRep; char* message_ptr = (char*)ptr + sizeof(StatusRep); // NOLINT MemoryCopy(message_ptr, message.data(), message.size()); message_ptr[message.size()] = '\0'; // NOLINT AtomicStore(&rep->ref_count, 1); rep->code = code; rep->message = StringView(message_ptr, message.size()); m_rep = std::bit_cast(rep); Ensures((m_rep & 1U) == 0); } } void Status::Ref() const { if (!IsInline()) { auto* rep = std::bit_cast(m_rep); Expects(AtomicLoad(&rep->ref_count) > 0); AtomicFetchIncrement(&rep->ref_count); } } StatusCode Status::RepCode() const { Expects(!IsInline()); return std::bit_cast(m_rep)->code; } void Status::Unref() const { if (!IsInline()) { auto* rep = std::bit_cast(m_rep); Expects(AtomicLoad(&rep->ref_count) > 0); if (AtomicFetchDecrement(&rep->ref_count, MemoryOrder::kRelease) == 1) { AtomicFence(MemoryOrder::kAcquire); deimos_StaticAssert(std::is_trivially_destructible_v); allocator_api->system->Free( rep, (int64_t)sizeof(StatusRep) + rep->message.size() + 1); } } } void InitializeStatus(ApiRegistry* api_registry) { allocator_api = api_registry->Get(); } } // namespace deimos