summaryrefslogtreecommitdiffhomepage
path: root/compat
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-04 19:44:17 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-05 03:31:19 +0200
commit3c4301fde92c625df6d95f5094b7eb655c613171 (patch)
tree3c40dcb298983030b52d614a4c95d77f6c0fb425 /compat
parent5e00350a9373056ca32f9cfb03c2f0e0e4acf385 (diff)
a w
Diffstat (limited to 'compat')
-rw-r--r--compat/borrowed-ptr-fwd.hpp28
-rw-r--r--compat/borrowed-ptr.cpp37
-rw-r--r--compat/borrowed-ptr.hpp28
-rw-r--r--compat/borrowed-ptr.inl151
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