Add copy to status

This commit is contained in:
2025-01-04 22:55:46 +01:00
parent b62e554e97
commit b53fc9038f
3 changed files with 90 additions and 11 deletions

View File

@ -3,6 +3,7 @@
#include "asl/string.hpp" #include "asl/string.hpp"
#include "asl/atomic.hpp" #include "asl/atomic.hpp"
// @Todo Use custom allocator
using Allocator = asl::DefaultAllocator; using Allocator = asl::DefaultAllocator;
static Allocator g_allocator{}; static Allocator g_allocator{};
@ -11,13 +12,12 @@ namespace
struct StatusInternal struct StatusInternal
{ {
// @Todo Use custom allocator asl::string<Allocator> msg;
asl::string<> msg;
asl::status_code code; asl::status_code code;
asl::atomic<int32_t> ref_count; asl::atomic<int32_t> ref_count;
constexpr StatusInternal(asl::string_view msg_, asl::status_code code_) constexpr StatusInternal(asl::string_view msg_, asl::status_code code_)
: msg{msg_} : msg{msg_, g_allocator}
, code{code_} , code{code_}
{ {
atomic_store(&ref_count, 1); atomic_store(&ref_count, 1);
@ -32,10 +32,23 @@ asl::status::status(status_code code, string_view msg)
asl::status_code asl::status::code_internal() const asl::status_code asl::status::code_internal() const
{ {
ASL_ASSERT(m_payload && (bit_cast<uintptr_t>(m_payload) & 1) == 0); ASL_ASSERT(!is_inline());
return reinterpret_cast<const StatusInternal*>(m_payload)->code; return reinterpret_cast<const StatusInternal*>(m_payload)->code;
} }
asl::string_view asl::status::message_internal() const
{
ASL_ASSERT(!is_inline());
return reinterpret_cast<const StatusInternal*>(m_payload)->msg;
}
void asl::status::ref()
{
ASL_ASSERT(!is_inline());
auto* internal = reinterpret_cast<StatusInternal*>(m_payload);
atomic_fetch_increment(&internal->ref_count, memory_order::relaxed);
}
void asl::status::unref() void asl::status::unref()
{ {
ASL_ASSERT(!is_inline()); ASL_ASSERT(!is_inline());

View File

@ -49,7 +49,9 @@ class status
} }
status_code code_internal() const; status_code code_internal() const;
string_view message_internal() const;
void ref();
void unref(); void unref();
public: public:
@ -57,10 +59,7 @@ public:
constexpr ~status() constexpr ~status()
{ {
if (!is_inline()) if (!is_inline()) { unref(); }
{
unref();
}
} }
explicit constexpr status(status_code code) explicit constexpr status(status_code code)
@ -69,10 +68,27 @@ public:
status(status_code code, string_view msg); status(status_code code, string_view msg);
constexpr status(const status& other)
: m_payload{other.m_payload}
{
if (!is_inline()) { ref(); }
}
constexpr status(status&& other) constexpr status(status&& other)
: m_payload{exchange(other.m_payload, nullptr)} : m_payload{exchange(other.m_payload, nullptr)}
{} {}
constexpr status& operator=(const status& other)
{
if (&other != this)
{
if (!is_inline()) { unref(); }
m_payload = other.m_payload;
if (!is_inline()) { ref(); }
}
return *this;
}
constexpr status& operator=(status&& other) constexpr status& operator=(status&& other)
{ {
if (&other != this) if (&other != this)
@ -82,8 +98,6 @@ public:
return *this; return *this;
} }
// @Todo Copy constructor & assignment
constexpr bool ok() const constexpr bool ok() const
{ {
return m_payload == nullptr || code() == status_code::ok; return m_payload == nullptr || code() == status_code::ok;
@ -96,6 +110,15 @@ public:
{ {
return is_inline() ? code_inline() : code_internal(); return is_inline() ? code_inline() : code_internal();
} }
constexpr string_view message() const
{
if (!is_inline())
{
return message_internal();
}
return {};
}
}; };
} // namespace asl } // namespace asl

View File

@ -15,6 +15,7 @@ ASL_TEST(simple_code)
ASL_TEST_ASSERT(!s); ASL_TEST_ASSERT(!s);
ASL_TEST_ASSERT(!s.ok()); ASL_TEST_ASSERT(!s.ok());
ASL_TEST_ASSERT(s.code() == asl::status_code::runtime); ASL_TEST_ASSERT(s.code() == asl::status_code::runtime);
ASL_TEST_ASSERT(s.message() == ""_sv);
} }
ASL_TEST(with_message) ASL_TEST(with_message)
@ -23,5 +24,47 @@ ASL_TEST(with_message)
ASL_TEST_ASSERT(!s); ASL_TEST_ASSERT(!s);
ASL_TEST_ASSERT(!s.ok()); ASL_TEST_ASSERT(!s.ok());
ASL_TEST_ASSERT(s.code() == asl::status_code::internal); ASL_TEST_ASSERT(s.code() == asl::status_code::internal);
// @Todo test message ASL_TEST_ASSERT(s.message() == "We done goofed"_sv);
}
ASL_TEST(copy_inline)
{
asl::status s{asl::status_code::ok};
asl::status s2{asl::status_code::internal};
asl::status s3 = s;
ASL_TEST_ASSERT(s3.code() == asl::status_code::ok);
s3 = s2;
ASL_TEST_ASSERT(s3.code() == asl::status_code::internal);
}
ASL_TEST(copy_message)
{
asl::status s2;
{
asl::status s{asl::status_code::internal, "Oh no!"};
ASL_TEST_ASSERT(!s);
ASL_TEST_ASSERT(!s.ok());
ASL_TEST_ASSERT(s.code() == asl::status_code::internal);
ASL_TEST_ASSERT(s.message() == "Oh no!"_sv);
const asl::status s3{s}; // NOLINT
ASL_TEST_ASSERT(!s3);
ASL_TEST_ASSERT(!s3.ok());
ASL_TEST_ASSERT(s3.code() == asl::status_code::internal);
ASL_TEST_ASSERT(s3.message() == "Oh no!"_sv);
s2 = s;
ASL_TEST_ASSERT(!s2);
ASL_TEST_ASSERT(!s2.ok());
ASL_TEST_ASSERT(s2.code() == asl::status_code::internal);
ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv);
}
ASL_TEST_ASSERT(!s2);
ASL_TEST_ASSERT(!s2.ok());
ASL_TEST_ASSERT(s2.code() == asl::status_code::internal);
ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv);
} }