Add copy to status
This commit is contained in:
@ -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());
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user