diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-04 22:42:12 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-04 22:42:12 +0100 |
commit | b62e554e9763497e53bae0a3d5a895c1cdbf40de (patch) | |
tree | 2ea157145e0be6fd3175aa2cb93fc60bcb1be8ef /asl | |
parent | 688bc74ce0ab320cdfc6e73f6db75612968f74c4 (diff) |
Deallocate StatusInternal on drop
Diffstat (limited to 'asl')
-rw-r--r-- | asl/atomic.hpp | 10 | ||||
-rw-r--r-- | asl/status.cpp | 24 | ||||
-rw-r--r-- | asl/status.hpp | 39 |
3 files changed, 56 insertions, 17 deletions
diff --git a/asl/atomic.hpp b/asl/atomic.hpp index cf6968c..95c3715 100644 --- a/asl/atomic.hpp +++ b/asl/atomic.hpp @@ -18,33 +18,33 @@ template<typename T> struct atomic { T m_value{}; }; inline void atomic_fence(memory_order order) { - __atomic_thread_fence((int)order); + __atomic_thread_fence(static_cast<int>(order)); } template<is_integer T> inline void atomic_store(atomic<T>* a, T value, memory_order order = memory_order::relaxed) { - __atomic_store(&a->m_value, &value, (int)order); + __atomic_store(&a->m_value, &value, static_cast<int>(order)); } template<is_integer T> inline T atomic_load(atomic<T>* a, memory_order order = memory_order::relaxed) { T value; - __atomic_load(&a->m_value, &value, (int)order); + __atomic_load(&a->m_value, &value, static_cast<int>(order)); return value; } template<typename T> inline T atomic_fetch_increment(atomic<T>* a, memory_order order = memory_order::relaxed) { - return __atomic_fetch_add(&a->m_value, 1, (int)order); + return __atomic_fetch_add(&a->m_value, 1, static_cast<int>(order)); } template<typename T> inline T atomic_fetch_decrement(atomic<T>* a, memory_order order = memory_order::relaxed) { - return __atomic_fetch_sub(&a->m_value, 1, (int)order); + return __atomic_fetch_sub(&a->m_value, 1, static_cast<int>(order)); } } // namespace asl diff --git a/asl/status.cpp b/asl/status.cpp index ac0b29e..eb26111 100644 --- a/asl/status.cpp +++ b/asl/status.cpp @@ -1,5 +1,7 @@ #include "asl/status.hpp" #include "asl/allocator.hpp" +#include "asl/string.hpp" +#include "asl/atomic.hpp" using Allocator = asl::DefaultAllocator; static Allocator g_allocator{}; @@ -9,8 +11,17 @@ namespace struct StatusInternal { - asl::string_view msg; + // @Todo Use custom allocator + asl::string<> msg; asl::status_code code; + asl::atomic<int32_t> ref_count; + + constexpr StatusInternal(asl::string_view msg_, asl::status_code code_) + : msg{msg_} + , code{code_} + { + atomic_store(&ref_count, 1); + } }; } // anonymous namespace @@ -25,3 +36,14 @@ asl::status_code asl::status::code_internal() const return reinterpret_cast<const StatusInternal*>(m_payload)->code; } +void asl::status::unref() +{ + ASL_ASSERT(!is_inline()); + auto* internal = reinterpret_cast<StatusInternal*>(m_payload); + if (atomic_fetch_decrement(&internal->ref_count, memory_order::release) == 1) + { + atomic_fence(memory_order::acquire); + alloc_delete(g_allocator, internal); + } +} + diff --git a/asl/status.hpp b/asl/status.hpp index 3d93213..c494759 100644 --- a/asl/status.hpp +++ b/asl/status.hpp @@ -6,6 +6,8 @@ namespace asl { +// @Todo Make status with formatting + enum class status_code : uint8_t { ok = 0, @@ -31,10 +33,35 @@ class status return static_cast<status_code>(bit_cast<uintptr_t>(payload) >> 1); } + constexpr bool is_inline() const + { + return m_payload == nullptr || (bit_cast<uintptr_t>(m_payload) & 1) != 0; + } + + constexpr status_code code_inline() const + { + ASL_ASSERT(is_inline()); + if (m_payload == nullptr) + { + return status_code::ok; + } + return payload_to_status(m_payload); + } + status_code code_internal() const; + + void unref(); public: constexpr status() = default; + + constexpr ~status() + { + if (!is_inline()) + { + unref(); + } + } explicit constexpr status(status_code code) : m_payload{status_to_payload(code)} @@ -67,17 +94,7 @@ public: constexpr status_code code() const { - if (m_payload == nullptr) - { - return status_code::ok; - } - - if ((bit_cast<uintptr_t>(m_payload) & 1) != 0) - { - return payload_to_status(m_payload); - } - - return code_internal(); + return is_inline() ? code_inline() : code_internal(); } }; |