diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-04 19:44:17 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-05 03:31:19 +0200 |
commit | 3c4301fde92c625df6d95f5094b7eb655c613171 (patch) | |
tree | 3c40dcb298983030b52d614a4c95d77f6c0fb425 /compat | |
parent | 5e00350a9373056ca32f9cfb03c2f0e0e4acf385 (diff) |
a w
Diffstat (limited to 'compat')
-rw-r--r-- | compat/borrowed-ptr-fwd.hpp | 28 | ||||
-rw-r--r-- | compat/borrowed-ptr.cpp | 37 | ||||
-rw-r--r-- | compat/borrowed-ptr.hpp | 28 | ||||
-rw-r--r-- | 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<typename T> class bptr; +template<typename T> bool operator==(const bptr<T>& a, const bptr<T>& b) noexcept; + template<typename T> 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<typename... Ts> requires std::is_constructible_v<T, Ts&&...> 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<typename Y> requires std::is_convertible_v<Y*, T*> bptr(const bptr<Y>&) noexcept; - template<typename Y> requires std::is_convertible_v<Y*, T*> bptr(bptr<Y>&&) noexcept; template<typename Y> requires std::is_convertible_v<Y*, T*> bptr& operator=(const bptr<Y>&) noexcept; + template<typename Y> requires std::is_convertible_v<Y*, T*> bptr(bptr<Y>&&) noexcept; template<typename Y> requires std::is_convertible_v<Y*, T*> bptr& operator=(bptr<Y>&&) noexcept; + friend bool operator==<T>(const bptr<T>& a, const bptr<T>& b) noexcept; + explicit operator bool() const noexcept; + void reset() noexcept; + template<bool MaybeEmpty = true> 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<typename U> friend class bptr; template<typename Tʹ, typename U> friend bptr<U> static_pointer_cast(const bptr<Tʹ>& 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<Foo>; +template struct detail_borrowed_ptr::control_block_impl<Foo>; template class bptr<Foo>; template bptr<Bar> static_pointer_cast(const bptr<Foo>&) 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<typename T> constexpr bptr<T>::bptr(std::nullptr_t) noexcept: ptr{nullptr}, blk{nullptr} {} -template<typename T> constexpr bptr<T>::bptr() noexcept: bptr{nullptr} {} - -template<typename T> constexpr T* bptr<T>::get() const noexcept { return ptr; } -template<typename T> constexpr T& bptr<T>::operator*() const noexcept { fm_debug_assert(ptr); return *ptr; } -template<typename T> constexpr T* bptr<T>::operator->() const noexcept { fm_debug_assert(ptr); return ptr; } - template<typename T, typename U> bptr<U> static_pointer_cast(const bptr<T>& p) noexcept { static_assert(detail_borrowed_ptr::StaticCastable<T, U>); - if (auto* blk = p.blk) [[likely]] + if (p.blk) [[likely]] { - auto* ptr = static_cast<U*>(p.ptr); - blk->incr(); - return bptr<U>{DirectInit, ptr, blk}; + if (auto* ptr = p.blk->_ptr) + { + fm_bptr_assert(p.casted_ptr); + auto* ret = static_cast<U*>(p.casted_ptr); + return bptr<U>{DirectInit, ret, p.blk}; + } } - else - return bptr<U>{nullptr}; + return bptr<U>{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<typename T> -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 <typename T> -control_block<T>::control_block(T* ptr) noexcept: - control_block_{ptr} +control_block_impl<T>::control_block_impl(T* ptr) noexcept { fm_bptr_assert(ptr); + _ptr = ptr; + _count = 1; } template <typename T> -void control_block<T>::free() noexcept +void control_block_impl<T>::free_ptr() noexcept { delete static_cast<T*>(_ptr); } template <typename T> -control_block_* control_block<T>::create(T* ptr) noexcept +control_block_* control_block_impl<T>::create(T* ptr) noexcept { - return ptr ? new control_block<T>{ptr} : nullptr; + if (ptr) + { + auto* __restrict ret = new control_block_impl<T>{ptr}; + return ret; + } + else + return nullptr; } } // namespace floormat::detail_borrowed_ptr namespace floormat { +template<typename T> bptr<T>::bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block_* blk) noexcept: + casted_ptr{casted_ptr}, blk{blk} +{} + +//template<typename T> bptr<T>::bptr(NoInitT) noexcept {} + template<typename T> template<typename... Ts> requires std::is_constructible_v<T, Ts&&...> @@ -68,68 +73,85 @@ bptr{ new T{ forward<Ts...>(args...) } } { } -template<typename T> constexpr bptr<T>::bptr(NoInitT) noexcept {}; - -template<typename T> -constexpr bptr<T>::bptr(DirectInitT, T* ptr, detail_borrowed_ptr::control_block_* blk) noexcept: - ptr{ptr}, blk{blk} -{ -} +template<typename T> bptr<T>::bptr(std::nullptr_t) noexcept: casted_ptr{nullptr}, blk{nullptr} {} +template<typename T> bptr<T>::bptr() noexcept: bptr{nullptr} {} template<typename T> bptr<T>::bptr(T* ptr) noexcept: - ptr{ptr}, - blk{detail_borrowed_ptr::control_block<T>::create(ptr)} + casted_ptr{ptr}, + blk{detail_borrowed_ptr::control_block_impl<T>::create(ptr)} { + fm_bptr_assert(blk && blk->_count == 1 && ptr && blk->_ptr); } template<typename T> bptr<T>::~bptr() noexcept { if (blk) - blk->decr(); - //blk = reinterpret_cast<T*>(-1); - //blk = nullptr; + blk->decrement(blk); } template<typename T> template<typename Y> requires std::is_convertible_v<Y*, T*> bptr<T>::bptr(const bptr<Y>& other) noexcept: - ptr{other.ptr}, blk{other.blk} + casted_ptr{other.casted_ptr}, blk{other.blk} { - static_assert(std::is_convertible_v<Y*, T*>); if (blk) - blk->incr(); - else - fm_bptr_assert(!ptr); + { + ++blk->_count; + fm_bptr_assert(blk->_count > 1); + } } template<typename T> template<typename Y> requires std::is_convertible_v<Y*, T*> -bptr<T>::bptr(bptr<Y>&& other) noexcept: ptr{other.ptr}, blk{other.blk} +bptr<T>::bptr(bptr<Y>&& other) noexcept: + casted_ptr{other.casted_ptr}, blk{other.blk} { - other.ptr = nullptr; + other.casted_ptr = nullptr; other.blk = nullptr; } template<typename T> +void bptr<T>::reset() noexcept +{ + if (blk) + { + fm_bptr_assert(casted_ptr); + blk->decrement(blk); + casted_ptr = nullptr; + blk = nullptr; + } +} + +template<typename T> +template<bool MaybeEmpty> +void bptr<T>::destroy() noexcept +{ + if constexpr(!MaybeEmpty) + fm_assert(blk && blk->_ptr); + blk->free_ptr(); + blk->_ptr = nullptr; + casted_ptr = nullptr; +} + +template<typename T> bptr<T>& bptr<T>::operator=(std::nullptr_t) noexcept { reset(); return *this; } + +template<typename T> template<typename Y> requires std::is_convertible_v<Y*, T*> bptr<T>& bptr<T>::operator=(const bptr<Y>& other) noexcept { - static_assert(std::is_convertible_v<Y*, T*>); - 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<typename Y> requires std::is_convertible_v<Y*, T*> bptr<T>& bptr<T>::operator=(bptr<Y>&& 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<typename T> T* bptr<T>::get() const noexcept +{ + if (blk && blk->_ptr) + { + fm_bptr_assert(casted_ptr); + return casted_ptr; + } + else + return nullptr; +} +template<typename T> T* bptr<T>::operator->() const noexcept +{ + auto* ret = get(); + fm_bptr_assert(ret); + return ret; +} + +template<typename T> T& bptr<T>::operator*() const noexcept { return *operator->(); } +template<typename T> bool operator==(const bptr<T>& a, const bptr<T>& b) noexcept { return a.blk == b.blk; } +template<typename T> bptr<T>::operator bool() const noexcept { return get(); } + template<typename T> void bptr<T>::swap(bptr& other) noexcept { using floormat::swap; - swap(ptr, other.ptr); + swap(casted_ptr, other.casted_ptr); swap(blk, other.blk); } template<typename T> uint32_t bptr<T>::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 |