Make status implementation more correct wrt type punning
This commit is contained in:
@ -35,6 +35,13 @@ template<typename T, typename U>
|
|||||||
return static_cast<return_type>(x);
|
return static_cast<return_type>(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] constexpr T* launder(T* ptr) noexcept // NOLINT
|
||||||
|
requires (!asl::is_func<T> && !asl::is_void<T>)
|
||||||
|
{
|
||||||
|
return __builtin_launder(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
|
@ -110,7 +110,9 @@ private:
|
|||||||
constexpr void set_size_inline(isize_t new_size)
|
constexpr void set_size_inline(isize_t new_size)
|
||||||
{
|
{
|
||||||
ASL_ASSERT(new_size >= 0 && new_size <= kInlineCapacity);
|
ASL_ASSERT(new_size >= 0 && new_size <= kInlineCapacity);
|
||||||
const size_t size_encoded = (load_size_encoded() & size_t{0x00ff'ffff'ffff'ffff}) | (bit_cast<size_t>(new_size) << 56U);
|
const size_t size_encoded =
|
||||||
|
(load_size_encoded() & size_t{0x00ff'ffff'ffff'ffff})
|
||||||
|
| (bit_cast<size_t>(new_size) << 56U);
|
||||||
store_size_encoded(size_encoded);
|
store_size_encoded(size_encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ using Allocator = asl::DefaultAllocator;
|
|||||||
// NOLINTNEXTLINE(*-non-const-global-variables)
|
// NOLINTNEXTLINE(*-non-const-global-variables)
|
||||||
static Allocator g_allocator{};
|
static Allocator g_allocator{};
|
||||||
|
|
||||||
namespace
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
struct StatusInternal
|
struct StatusInternal
|
||||||
@ -33,7 +33,7 @@ struct StatusInternal
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // namespace asl
|
||||||
|
|
||||||
asl::status::status(status_code code, string_view msg)
|
asl::status::status(status_code code, string_view msg)
|
||||||
: m_payload{alloc_new<StatusInternal>(g_allocator, msg, code)}
|
: m_payload{alloc_new<StatusInternal>(g_allocator, msg, code)}
|
||||||
@ -49,34 +49,29 @@ asl::status::status(status_code code, string_view fmt, span<format_internals::ty
|
|||||||
asl::status_code asl::status::code_internal() const
|
asl::status_code asl::status::code_internal() const
|
||||||
{
|
{
|
||||||
ASL_ASSERT(!is_inline());
|
ASL_ASSERT(!is_inline());
|
||||||
// NOLINTNEXTLINE(*-reinterpret-cast)
|
return m_payload->code;
|
||||||
return reinterpret_cast<const StatusInternal*>(m_payload)->code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asl::string_view asl::status::message_internal() const
|
asl::string_view asl::status::message_internal() const
|
||||||
{
|
{
|
||||||
ASL_ASSERT(!is_inline());
|
ASL_ASSERT(!is_inline());
|
||||||
// NOLINTNEXTLINE(*-reinterpret-cast)
|
return m_payload->msg;
|
||||||
return reinterpret_cast<const StatusInternal*>(m_payload)->msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::status::ref()
|
void asl::status::ref()
|
||||||
{
|
{
|
||||||
ASL_ASSERT(!is_inline());
|
ASL_ASSERT(!is_inline());
|
||||||
// NOLINTNEXTLINE(*-reinterpret-cast)
|
atomic_fetch_increment(&m_payload->ref_count, memory_order::relaxed);
|
||||||
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());
|
||||||
// NOLINTNEXTLINE(*-reinterpret-cast)
|
if (atomic_fetch_decrement(&m_payload->ref_count, memory_order::release) == 1)
|
||||||
auto* internal = reinterpret_cast<StatusInternal*>(m_payload);
|
|
||||||
if (atomic_fetch_decrement(&internal->ref_count, memory_order::release) == 1)
|
|
||||||
{
|
{
|
||||||
atomic_fence(memory_order::acquire);
|
atomic_fence(memory_order::acquire);
|
||||||
alloc_delete(g_allocator, internal);
|
alloc_delete(g_allocator, m_payload);
|
||||||
|
m_payload = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,15 +22,17 @@ enum class status_code : uint8_t
|
|||||||
invalid_argument = 4,
|
invalid_argument = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StatusInternal;
|
||||||
|
|
||||||
class status
|
class status
|
||||||
{
|
{
|
||||||
void* m_payload{};
|
StatusInternal* m_payload{};
|
||||||
|
|
||||||
static constexpr void* status_to_payload(status_code code)
|
static constexpr StatusInternal* status_to_payload(status_code code)
|
||||||
{
|
{
|
||||||
return code == status_code::ok
|
return code == status_code::ok
|
||||||
? nullptr
|
? nullptr
|
||||||
: bit_cast<void*>((static_cast<uintptr_t>(code) << 1) | 1);
|
: bit_cast<StatusInternal*>((static_cast<uintptr_t>(code) << 1) | 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr status_code payload_to_status(void* payload)
|
static constexpr status_code payload_to_status(void* payload)
|
||||||
|
Reference in New Issue
Block a user