memory: add dynamicPointerCast for weak ptrs

closes #102
This commit is contained in:
Vaxry 2026-03-07 18:28:56 +00:00
parent e63f3a7933
commit 8eb974bdea
Signed by: vaxry
GPG key ID: 665806380871D640
4 changed files with 35 additions and 6 deletions

View file

@ -285,6 +285,10 @@ namespace Hyprutils::Memory {
CAtomicWeakPointer() noexcept = default;
CAtomicWeakPointer(Impl_::impl_base* implementation, void* data) noexcept : m_ptr(implementation, data) {
;
}
CAtomicWeakPointer(std::nullptr_t) noexcept {
; // empty
}
@ -434,4 +438,14 @@ namespace Hyprutils::Memory {
return nullptr;
return CAtomicSharedPointer<T>(ref.impl(), newPtr);
}
template <typename T, typename U>
CAtomicWeakPointer<T> dynamicPointerCast(const CAtomicWeakPointer<U>& ref) {
if (!ref)
return nullptr;
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl()->getData()));
if (!newPtr)
return nullptr;
return CAtomicWeakPointer<T>(ref.impl(), newPtr);
}
}

View file

@ -62,6 +62,14 @@ namespace Hyprutils {
incrementWeak();
}
CWeakPointer(Impl_::impl_base* implementation, void* data) noexcept : impl_(implementation), m_data(data) {
incrementWeak();
}
CWeakPointer(std::nullptr_t) noexcept {
; // empty
}
template <typename U, typename = isConstructible<U>>
CWeakPointer(CWeakPointer<U>&& ref) noexcept {
std::swap(impl_, ref.impl_);

View file

@ -10,10 +10,10 @@ using namespace Hyprutils::Memory;
#define WP CWeakPointer
void Hyprutils::Signal::CSignalBase::emitInternal(void* args) {
// Save, an event can destroy thisptr
const auto STATICS = m_vStaticListeners;
if (!m_vListeners.empty()) {
std::vector<SP<CSignalListener>> listeners;
listeners.reserve(m_vListeners.size());

View file

@ -156,8 +156,10 @@ static void testHierarchy() {
EXPECT_TRUE(ifaceA);
EXPECT_EQ(ifaceA->m_ifaceAInt, 69);
auto ifaceB = dynamicPointerCast<InterfaceA>(SP<CChildA>{});
auto ifaceB = dynamicPointerCast<InterfaceA>(SP<CChildA>{});
auto ifaceB2 = dynamicPointerCast<InterfaceA>(WP<CChildA>{});
EXPECT_TRUE(!ifaceB);
EXPECT_TRUE(!ifaceB2);
}
{
@ -171,9 +173,11 @@ static void testHierarchy() {
EXPECT_EQ(ifaceB->m_ifaceBInt, 2);
WP<InterfaceA> ifaceAWeak = ifaceA;
WP<InterfaceB> ifaceBWeak = dynamicPointerCast<InterfaceB>(WP<CChild>{child});
child.reset();
EXPECT_TRUE(ifaceAWeak);
EXPECT_TRUE(ifaceBWeak);
EXPECT_TRUE(ifaceA);
EXPECT_EQ(ifaceAWeak->m_ifaceAInt, 69);
EXPECT_EQ(ifaceA->m_ifaceAInt, 69);
@ -182,8 +186,10 @@ static void testHierarchy() {
EXPECT_EQ(ifaceAWeak->m_ifaceAInt, 69);
EXPECT_TRUE(ifaceB);
EXPECT_EQ(ifaceB->m_ifaceBInt, 2);
EXPECT_EQ(ifaceBWeak->m_ifaceBInt, 2);
ifaceB.reset();
EXPECT_TRUE(!ifaceAWeak);
EXPECT_TRUE(!ifaceBWeak);
}
//
@ -194,8 +200,10 @@ static void testHierarchy() {
EXPECT_TRUE(ifaceA);
EXPECT_EQ(ifaceA->m_ifaceAInt, 69);
auto ifaceB = dynamicPointerCast<InterfaceA>(ASP<CChildA>{});
auto ifaceB = dynamicPointerCast<InterfaceA>(SP<CChildA>{});
auto ifaceB2 = dynamicPointerCast<InterfaceA>(WP<CChildA>{});
EXPECT_TRUE(!ifaceB);
EXPECT_TRUE(!ifaceB2);
}
{
@ -209,7 +217,7 @@ static void testHierarchy() {
EXPECT_EQ(ifaceB->m_ifaceBInt, 2);
AWP<InterfaceA> ifaceAWeak = ifaceA;
AWP<InterfaceB> ifaceBWeak = dynamicPointerCast<InterfaceB>(ifaceA);
AWP<InterfaceB> ifaceBWeak = dynamicPointerCast<InterfaceB>(AWP<CChild>{child});
child.reset();
EXPECT_TRUE(ifaceAWeak);
@ -217,7 +225,6 @@ static void testHierarchy() {
EXPECT_TRUE(ifaceA);
EXPECT_EQ(ifaceAWeak->m_ifaceAInt, 69);
EXPECT_EQ(ifaceA->m_ifaceAInt, 69);
EXPECT_EQ(ifaceBWeak->m_ifaceBInt, 2);
ifaceA.reset();
EXPECT_TRUE(ifaceAWeak);
EXPECT_EQ(ifaceAWeak->m_ifaceAInt, 69);