Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions include/hyprutils/memory/Atomic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ namespace Hyprutils::Memory {
using validHierarchy = std::enable_if_t<std::is_assignable_v<CAtomicSharedPointer<T>&, X>, CAtomicSharedPointer&>;

public:
explicit CAtomicSharedPointer(T* object) noexcept : m_ptr(new Atomic_::impl(sc<void*>(object), _delete)) {
explicit CAtomicSharedPointer(T* object) noexcept : m_ptr(new Atomic_::impl(sc<void*>(object), _delete), sc<void*>(object)) {
;
}

CAtomicSharedPointer(Impl_::impl_base* impl) noexcept : m_ptr(impl) {
CAtomicSharedPointer(Impl_::impl_base* impl, void* data) noexcept : m_ptr(impl, data) {
;
}

Expand Down Expand Up @@ -219,13 +219,17 @@ namespace Hyprutils::Memory {
return m_ptr.impl_ ? m_ptr.impl_->ref() : 0;
}

Atomic_::impl* impl() const {
return sc<Atomic_::impl*>(m_ptr.impl_);
}

private:
static void _delete(void* p) {
std::default_delete<T>{}(sc<T*>(p));
}

std::lock_guard<std::recursive_mutex> implLockGuard() const {
return sc<Atomic_::impl*>(m_ptr.impl_)->lockGuard();
return impl()->lockGuard();
}

CSharedPointer<T> m_ptr;
Expand Down Expand Up @@ -391,12 +395,16 @@ namespace Hyprutils::Memory {
if (!m_ptr.impl_->dataNonNull() || m_ptr.impl_->destroying() || !m_ptr.impl_->lockable())
return {};

return CAtomicSharedPointer<T>(m_ptr.impl_);
return CAtomicSharedPointer<T>(m_ptr.impl_, m_ptr.m_data);
}

Atomic_::impl* impl() const {
return sc<Atomic_::impl*>(m_ptr.impl_);
}

private:
std::lock_guard<std::recursive_mutex> implLockGuard() const {
return sc<Atomic_::impl*>(m_ptr.impl_)->lockGuard();
return impl()->lockGuard();
}

CWeakPointer<T> m_ptr;
Expand All @@ -411,4 +419,19 @@ namespace Hyprutils::Memory {
[[nodiscard]] inline CAtomicSharedPointer<U> makeAtomicShared(Args&&... args) {
return CAtomicSharedPointer<U>(new U(std::forward<Args>(args)...));
}

template <typename T, typename U>
CAtomicSharedPointer<T> reinterpretPointerCast(const CAtomicSharedPointer<U>& ref) {
return CAtomicSharedPointer<T>(ref.impl(), ref.m_data);
}

template <typename T, typename U>
CAtomicSharedPointer<T> dynamicPointerCast(const CAtomicSharedPointer<U>& ref) {
if (!ref)
return nullptr;
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl()->getData()));
if (!newPtr)
return nullptr;
return CAtomicSharedPointer<T>(ref.impl(), newPtr);
}
}
40 changes: 31 additions & 9 deletions include/hyprutils/memory/SharedPtr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,33 @@ namespace Hyprutils {

/* creates a new shared pointer managing a resource
avoid calling. Could duplicate ownership. Prefer makeShared */
explicit CSharedPointer(T* object) noexcept : impl_(new Impl_::impl_base(sc<void*>(object), _delete)) {
explicit CSharedPointer(T* object) noexcept : impl_(new Impl_::impl_base(sc<void*>(object), _delete)), m_data(sc<void*>(object)) {
increment();
}

/* creates a shared pointer from a reference */
template <typename U, typename = isConstructible<U>>
CSharedPointer(const CSharedPointer<U>& ref) noexcept : impl_(ref.impl_) {
CSharedPointer(const CSharedPointer<U>& ref) noexcept : impl_(ref.impl_), m_data(ref.m_data) {
increment();
}

CSharedPointer(const CSharedPointer& ref) noexcept : impl_(ref.impl_) {
CSharedPointer(const CSharedPointer& ref) noexcept : impl_(ref.impl_), m_data(ref.m_data) {
increment();
}

template <typename U, typename = isConstructible<U>>
CSharedPointer(CSharedPointer<U>&& ref) noexcept {
std::swap(impl_, ref.impl_);
std::swap(m_data, ref.m_data);
}

CSharedPointer(CSharedPointer&& ref) noexcept {
std::swap(impl_, ref.impl_);
std::swap(m_data, ref.m_data);
}

/* allows weakPointer to create from an impl */
CSharedPointer(Impl_::impl_base* implementation) noexcept : impl_(implementation) {
CSharedPointer(Impl_::impl_base* implementation, void* data) noexcept : impl_(implementation), m_data(data) {
increment();
}

Expand All @@ -74,7 +76,8 @@ namespace Hyprutils {
return *this;

decrement();
impl_ = rhs.impl_;
impl_ = rhs.impl_;
m_data = rhs.m_data;
increment();
return *this;
}
Expand All @@ -84,26 +87,31 @@ namespace Hyprutils {
return *this;

decrement();
impl_ = rhs.impl_;
impl_ = rhs.impl_;
m_data = rhs.m_data;
increment();
return *this;
}

template <typename U>
validHierarchy<const CSharedPointer<U>&> operator=(CSharedPointer<U>&& rhs) {
std::swap(impl_, rhs.impl_);
std::swap(m_data, rhs.m_data);
return *this;
}

CSharedPointer& operator=(CSharedPointer&& rhs) noexcept {
std::swap(impl_, rhs.impl_);
std::swap(m_data, rhs.m_data);
return *this;
}

operator bool() const {
return impl_ && impl_->dataNonNull();
}

// this compares that the pointed-to object is the same, but in multiple inheritance,
// different typed pointers can be equal if the object is the same
bool operator==(const CSharedPointer& rhs) const {
return impl_ == rhs.impl_;
}
Expand All @@ -126,11 +134,12 @@ namespace Hyprutils {

void reset() {
decrement();
impl_ = nullptr;
impl_ = nullptr;
m_data = nullptr;
}

T* get() const {
return impl_ ? sc<T*>(impl_->getData()) : nullptr;
return impl_ && impl_->dataNonNull() ? sc<T*>(m_data) : nullptr;
}

unsigned int strongRef() const {
Expand All @@ -139,6 +148,9 @@ namespace Hyprutils {

Impl_::impl_base* impl_ = nullptr;

// Never use directly: raw data ptr, could be UAF
void* m_data = nullptr;

private:
static void _delete(void* p) {
std::default_delete<T>{}(sc<T*>(p));
Expand Down Expand Up @@ -188,7 +200,17 @@ namespace Hyprutils {

template <typename T, typename U>
CSharedPointer<T> reinterpretPointerCast(const CSharedPointer<U>& ref) {
return CSharedPointer<T>(ref.impl_);
return CSharedPointer<T>(ref.impl_, ref.m_data);
}

template <typename T, typename U>
CSharedPointer<T> dynamicPointerCast(const CSharedPointer<U>& ref) {
if (!ref)
return nullptr;
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl_->getData()));
if (!newPtr)
return nullptr;
return CSharedPointer<T>(ref.impl_, newPtr);
}
}
}
Expand Down
43 changes: 33 additions & 10 deletions include/hyprutils/memory/WeakPtr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ namespace Hyprutils {
if (!ref.impl_)
return;

impl_ = ref.impl_;
impl_ = ref.impl_;
m_data = ref.m_data;
incrementWeak();
}

Expand All @@ -36,7 +37,8 @@ namespace Hyprutils {
if (!ref.impl_)
return;

impl_ = ref.impl_;
impl_ = ref.impl_;
m_data = ref.impl_->getData();
incrementWeak();
}

Expand All @@ -46,25 +48,29 @@ namespace Hyprutils {
if (!ref.impl_)
return;

impl_ = ref.impl_;
impl_ = ref.impl_;
m_data = ref.m_data;
incrementWeak();
}

CWeakPointer(const CWeakPointer& ref) noexcept {
if (!ref.impl_)
return;

impl_ = ref.impl_;
impl_ = ref.impl_;
m_data = ref.m_data;
incrementWeak();
}

template <typename U, typename = isConstructible<U>>
CWeakPointer(CWeakPointer<U>&& ref) noexcept {
std::swap(impl_, ref.impl_);
std::swap(m_data, ref.m_data);
}

CWeakPointer(CWeakPointer&& ref) noexcept {
std::swap(impl_, ref.impl_);
std::swap(m_data, ref.m_data);
}

/* create a weak ptr from another weak ptr with assignment */
Expand All @@ -74,7 +80,8 @@ namespace Hyprutils {
return *this;

decrementWeak();
impl_ = rhs.impl_;
impl_ = rhs.impl_;
m_data = rhs.m_data;
incrementWeak();
return *this;
}
Expand All @@ -84,7 +91,8 @@ namespace Hyprutils {
return *this;

decrementWeak();
impl_ = rhs.impl_;
impl_ = rhs.impl_;
m_data = rhs.m_data;
incrementWeak();
return *this;
}
Expand All @@ -96,7 +104,8 @@ namespace Hyprutils {
return *this;

decrementWeak();
impl_ = rhs.impl_;
impl_ = rhs.impl_;
m_data = rhs.m_data;
incrementWeak();
return *this;
}
Expand Down Expand Up @@ -125,14 +134,15 @@ namespace Hyprutils {

void reset() {
decrementWeak();
impl_ = nullptr;
impl_ = nullptr;
m_data = nullptr;
}

CSharedPointer<T> lock() const {
if (!impl_ || !impl_->dataNonNull() || impl_->destroying() || !impl_->lockable())
return {};

return CSharedPointer<T>(impl_);
return CSharedPointer<T>(impl_, m_data);
}

/* this returns valid() */
Expand Down Expand Up @@ -169,7 +179,7 @@ namespace Hyprutils {
}

T* get() const {
return impl_ ? sc<T*>(impl_->getData()) : nullptr;
return impl_ && impl_->dataNonNull() ? sc<T*>(m_data) : nullptr;
}

T* operator->() const {
Expand All @@ -182,6 +192,9 @@ namespace Hyprutils {

Impl_::impl_base* impl_ = nullptr;

// Never use directly: raw data ptr, could be UAF
void* m_data = nullptr;

private:
/* no-op if there is no impl_ */
void decrementWeak() {
Expand All @@ -207,6 +220,16 @@ namespace Hyprutils {
impl_->incWeak();
}
};

template <typename T, typename U>
CWeakPointer<T> dynamicPointerCast(const CWeakPointer<U>& ref) {
if (!ref)
return nullptr;
T* newPtr = dynamic_cast<T*>(sc<U*>(ref.impl_->getData()));
if (!newPtr)
return nullptr;
return CWeakPointer<T>(ref.impl_, newPtr);
}
}
}

Expand Down
Loading