summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-04 22:42:12 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-04 22:42:12 +0100
commitb62e554e9763497e53bae0a3d5a895c1cdbf40de (patch)
tree2ea157145e0be6fd3175aa2cb93fc60bcb1be8ef /asl
parent688bc74ce0ab320cdfc6e73f6db75612968f74c4 (diff)
Deallocate StatusInternal on drop
Diffstat (limited to 'asl')
-rw-r--r--asl/atomic.hpp10
-rw-r--r--asl/status.cpp24
-rw-r--r--asl/status.hpp39
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();
}
};