From 3c4301fde92c625df6d95f5094b7eb655c613171 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 4 May 2024 19:44:17 +0200 Subject: a w --- compat/borrowed-ptr-fwd.hpp | 28 +++++--- compat/borrowed-ptr.cpp | 37 +++++------ compat/borrowed-ptr.hpp | 28 ++++---- compat/borrowed-ptr.inl | 151 +++++++++++++++++++++++++++----------------- 4 files changed, 142 insertions(+), 102 deletions(-) diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp index df985fd7..da91502d 100644 --- a/compat/borrowed-ptr-fwd.hpp +++ b/compat/borrowed-ptr-fwd.hpp @@ -4,36 +4,44 @@ namespace floormat::detail_borrowed_ptr { struct control_block_; } namespace floormat { +template class bptr; +template bool operator==(const bptr& a, const bptr& b) noexcept; + template class bptr final // NOLINT(*-special-member-functions) { - mutable T* ptr; + mutable T* casted_ptr; detail_borrowed_ptr::control_block_* blk; - explicit constexpr bptr(NoInitT) noexcept; - explicit constexpr bptr(DirectInitT, T* ptr, detail_borrowed_ptr::control_block_* blk) noexcept; + explicit bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block_* blk) noexcept; + //explicit bptr(NoInitT) noexcept; public: template requires std::is_constructible_v explicit bptr(InPlaceInitT, Ts&&... args) noexcept; - constexpr bptr(std::nullptr_t) noexcept; // NOLINT(*-explicit-conversions) - constexpr bptr() noexcept; + bptr(std::nullptr_t) noexcept; // NOLINT(*-explicit-conversions) + bptr() noexcept; explicit bptr(T* ptr) noexcept; ~bptr() noexcept; + bptr& operator=(std::nullptr_t) noexcept; template requires std::is_convertible_v bptr(const bptr&) noexcept; - template requires std::is_convertible_v bptr(bptr&&) noexcept; template requires std::is_convertible_v bptr& operator=(const bptr&) noexcept; + template requires std::is_convertible_v bptr(bptr&&) noexcept; template requires std::is_convertible_v bptr& operator=(bptr&&) noexcept; + friend bool operator==(const bptr& a, const bptr& b) noexcept; + explicit operator bool() const noexcept; + void reset() noexcept; + template void destroy() noexcept; void swap(bptr& other) noexcept; - constexpr T* get() const noexcept; - constexpr T& operator*() const noexcept; - constexpr T* operator->() const noexcept; uint32_t use_count() const noexcept; - explicit operator bool() const noexcept; + + T* get() const noexcept; + T* operator->() const noexcept; + T& operator*() const noexcept; template friend class bptr; template friend bptr static_pointer_cast(const bptr& p) noexcept; diff --git a/compat/borrowed-ptr.cpp b/compat/borrowed-ptr.cpp index cc4bf54e..9039a8db 100644 --- a/compat/borrowed-ptr.cpp +++ b/compat/borrowed-ptr.cpp @@ -3,31 +3,26 @@ namespace floormat::detail_borrowed_ptr { -control_block_::control_block_(void* ptr) noexcept: _ptr{ptr}, _count{1} +#ifdef __GNUG__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdelete-abstract-non-virtual-dtor" +#endif +void control_block_::decrement(control_block_*& blk) noexcept { - fm_bptr_assert(ptr); -} - -void control_block_::incr() noexcept -{ - auto val = ++_count; - (void)val; - fm_bptr_assert(val > 1); -} - -void control_block_::decr() noexcept -{ - auto val = --_count; - fm_bptr_assert(val != (uint32_t)-1); - if (val == 0) + fm_bptr_assert(blk); + auto c = --blk->_count; + fm_bptr_assert(c != (uint32_t)-1); + if (c == 0) { - free(); - _ptr = nullptr; + blk->free_ptr(); + delete blk; } + blk = nullptr; } -control_block_::~control_block_() noexcept { decr(); } -uint32_t control_block_::count() const noexcept { return _count; } +#ifdef __GNUG__ +#pragma GCC diagnostic pop +#endif } // namespace floormat::detail_borrowed_ptr @@ -39,7 +34,7 @@ struct Baz {}; namespace floormat { -template struct detail_borrowed_ptr::control_block; +template struct detail_borrowed_ptr::control_block_impl; template class bptr; template bptr static_pointer_cast(const bptr&) noexcept; diff --git a/compat/borrowed-ptr.hpp b/compat/borrowed-ptr.hpp index d3feee2f..5caa2261 100644 --- a/compat/borrowed-ptr.hpp +++ b/compat/borrowed-ptr.hpp @@ -1,11 +1,16 @@ #pragma once #include "borrowed-ptr-fwd.hpp" #include "borrowed-ptr.inl" +#include "borrowed-ptr.inl" #define FM_BPTR_DEBUG + +#ifdef FM_NO_DEBUG +#undef FM_BPTR_DEBUG +#endif #ifdef FM_BPTR_DEBUG #include "compat/assert.hpp" -#define fm_bptr_assert(...) fm_debug_assert(__VA_ARGS__) +#define fm_bptr_assert(...) fm_assert(__VA_ARGS__) #else #define fm_bptr_assert(...) void() #endif @@ -23,26 +28,21 @@ concept StaticCastable = requires(From* from) { namespace floormat { -template constexpr bptr::bptr(std::nullptr_t) noexcept: ptr{nullptr}, blk{nullptr} {} -template constexpr bptr::bptr() noexcept: bptr{nullptr} {} - -template constexpr T* bptr::get() const noexcept { return ptr; } -template constexpr T& bptr::operator*() const noexcept { fm_debug_assert(ptr); return *ptr; } -template constexpr T* bptr::operator->() const noexcept { fm_debug_assert(ptr); return ptr; } - template bptr static_pointer_cast(const bptr& p) noexcept { static_assert(detail_borrowed_ptr::StaticCastable); - if (auto* blk = p.blk) [[likely]] + if (p.blk) [[likely]] { - auto* ptr = static_cast(p.ptr); - blk->incr(); - return bptr{DirectInit, ptr, blk}; + if (auto* ptr = p.blk->_ptr) + { + fm_bptr_assert(p.casted_ptr); + auto* ret = static_cast(p.casted_ptr); + return bptr{DirectInit, ret, p.blk}; + } } - else - return bptr{nullptr}; + return bptr{nullptr}; } } // namespace floormat diff --git a/compat/borrowed-ptr.inl b/compat/borrowed-ptr.inl index d468b231..feca62c0 100644 --- a/compat/borrowed-ptr.inl +++ b/compat/borrowed-ptr.inl @@ -10,17 +10,10 @@ namespace floormat::detail_borrowed_ptr { struct control_block_ { - explicit control_block_(void* ptr) noexcept; - ~control_block_() noexcept; - void incr() noexcept; - void decr() noexcept; - uint32_t count() const noexcept; - void* _ptr; // todo maybe add directly embeddable objects? uint32_t _count; - -private: - virtual void free() noexcept = 0; + virtual void free_ptr() noexcept = 0; + static void decrement(control_block_*& blk) noexcept; }; #ifdef __GNUG__ @@ -28,38 +21,50 @@ private: #endif template -struct control_block final: control_block_ +struct control_block_impl final: control_block_ { - void free() noexcept override; + void free_ptr() noexcept override; [[nodiscard]] static control_block_* create(T* ptr) noexcept; - protected: - explicit control_block(T* ptr) noexcept; + explicit control_block_impl(T* ptr) noexcept; }; template -control_block::control_block(T* ptr) noexcept: - control_block_{ptr} +control_block_impl::control_block_impl(T* ptr) noexcept { fm_bptr_assert(ptr); + _ptr = ptr; + _count = 1; } template -void control_block::free() noexcept +void control_block_impl::free_ptr() noexcept { delete static_cast(_ptr); } template -control_block_* control_block::create(T* ptr) noexcept +control_block_* control_block_impl::create(T* ptr) noexcept { - return ptr ? new control_block{ptr} : nullptr; + if (ptr) + { + auto* __restrict ret = new control_block_impl{ptr}; + return ret; + } + else + return nullptr; } } // namespace floormat::detail_borrowed_ptr namespace floormat { +template bptr::bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block_* blk) noexcept: + casted_ptr{casted_ptr}, blk{blk} +{} + +//template bptr::bptr(NoInitT) noexcept {} + template template requires std::is_constructible_v @@ -68,68 +73,85 @@ bptr{ new T{ forward(args...) } } { } -template constexpr bptr::bptr(NoInitT) noexcept {}; - -template -constexpr bptr::bptr(DirectInitT, T* ptr, detail_borrowed_ptr::control_block_* blk) noexcept: - ptr{ptr}, blk{blk} -{ -} +template bptr::bptr(std::nullptr_t) noexcept: casted_ptr{nullptr}, blk{nullptr} {} +template bptr::bptr() noexcept: bptr{nullptr} {} template bptr::bptr(T* ptr) noexcept: - ptr{ptr}, - blk{detail_borrowed_ptr::control_block::create(ptr)} + casted_ptr{ptr}, + blk{detail_borrowed_ptr::control_block_impl::create(ptr)} { + fm_bptr_assert(blk && blk->_count == 1 && ptr && blk->_ptr); } template bptr::~bptr() noexcept { if (blk) - blk->decr(); - //blk = reinterpret_cast(-1); - //blk = nullptr; + blk->decrement(blk); } template template requires std::is_convertible_v bptr::bptr(const bptr& other) noexcept: - ptr{other.ptr}, blk{other.blk} + casted_ptr{other.casted_ptr}, blk{other.blk} { - static_assert(std::is_convertible_v); if (blk) - blk->incr(); - else - fm_bptr_assert(!ptr); + { + ++blk->_count; + fm_bptr_assert(blk->_count > 1); + } } template template requires std::is_convertible_v -bptr::bptr(bptr&& other) noexcept: ptr{other.ptr}, blk{other.blk} +bptr::bptr(bptr&& other) noexcept: + casted_ptr{other.casted_ptr}, blk{other.blk} { - other.ptr = nullptr; + other.casted_ptr = nullptr; other.blk = nullptr; } +template +void bptr::reset() noexcept +{ + if (blk) + { + fm_bptr_assert(casted_ptr); + blk->decrement(blk); + casted_ptr = nullptr; + blk = nullptr; + } +} + +template +template +void bptr::destroy() noexcept +{ + if constexpr(!MaybeEmpty) + fm_assert(blk && blk->_ptr); + blk->free_ptr(); + blk->_ptr = nullptr; + casted_ptr = nullptr; +} + +template bptr& bptr::operator=(std::nullptr_t) noexcept { reset(); return *this; } + template template requires std::is_convertible_v bptr& bptr::operator=(const bptr& other) noexcept { - static_assert(std::is_convertible_v); - auto* const newblk = other.blk; - if (blk != newblk) + if (blk != other.blk) { - CORRADE_ASSUME(this != &other); - ptr = other.ptr; + CORRADE_ASSUME(this != &other); // todo! see if helps if (blk) - blk->decr(); - blk = newblk; - if (newblk) - newblk->incr(); + blk->decrement(blk); + casted_ptr = other.casted_ptr; + blk = other.blk; + ++blk->_count; } return *this; } @@ -139,34 +161,49 @@ template requires std::is_convertible_v bptr& bptr::operator=(bptr&& other) noexcept { - ptr = other.ptr; + blk->decrement(blk); + casted_ptr = other.casted_ptr; blk = other.blk; - other.ptr = nullptr; + other.casted_ptr = nullptr; other.blk = nullptr; return *this; } +template T* bptr::get() const noexcept +{ + if (blk && blk->_ptr) + { + fm_bptr_assert(casted_ptr); + return casted_ptr; + } + else + return nullptr; +} +template T* bptr::operator->() const noexcept +{ + auto* ret = get(); + fm_bptr_assert(ret); + return ret; +} + +template T& bptr::operator*() const noexcept { return *operator->(); } +template bool operator==(const bptr& a, const bptr& b) noexcept { return a.blk == b.blk; } +template bptr::operator bool() const noexcept { return get(); } + template void bptr::swap(bptr& other) noexcept { using floormat::swap; - swap(ptr, other.ptr); + swap(casted_ptr, other.casted_ptr); swap(blk, other.blk); } template uint32_t bptr::use_count() const noexcept { if (blk) [[likely]] - { - auto count = blk->_count; - fm_bptr_assert(count > 0); - return count; - } + return blk->_count; else - { - fm_bptr_assert(ptr); return 0; - } } } // namespace floormat -- cgit v1.2.3