diff --git a/AK/NonnullOwnPtr.h b/AK/NonnullOwnPtr.h new file mode 100644 index 00000000000..7c8c7817f2c --- /dev/null +++ b/AK/NonnullOwnPtr.h @@ -0,0 +1,157 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace AK { + +template +class RefPtr; +template +class NonnullRefPtr; +template +class WeakPtr; + +template +class CONSUMABLE(unconsumed) NonnullOwnPtr { +public: + enum AdoptTag { Adopt }; + + RETURN_TYPESTATE(unconsumed) + NonnullOwnPtr(AdoptTag, T& ptr) + : m_ptr(&ptr) + { + } + RETURN_TYPESTATE(unconsumed) + NonnullOwnPtr(NonnullOwnPtr&& other) + : m_ptr(other.leak_ptr()) + { + ASSERT(m_ptr); + } + template + RETURN_TYPESTATE(unconsumed) + NonnullOwnPtr(NonnullOwnPtr&& other) + : m_ptr(static_cast(other.leak_ptr())) + { + ASSERT(m_ptr); + } + ~NonnullOwnPtr() + { + clear(); +#ifdef SANITIZE_PTRS + if constexpr (sizeof(T*) == 8) + m_ptr = (T*)(0xe3e3e3e3e3e3e3e3); + else + m_ptr = (T*)(0xe3e3e3e3); +#endif + } + + NonnullOwnPtr(const NonnullOwnPtr&) = delete; + template + NonnullOwnPtr(const NonnullOwnPtr&) = delete; + NonnullOwnPtr& operator=(const NonnullOwnPtr&) = delete; + template + NonnullOwnPtr& operator=(const NonnullOwnPtr&) = delete; + + template + NonnullOwnPtr(const RefPtr&) = delete; + template + NonnullOwnPtr(const NonnullRefPtr&) = delete; + template + NonnullOwnPtr(const WeakPtr&) = delete; + template + NonnullOwnPtr& operator=(const RefPtr&) = delete; + template + NonnullOwnPtr& operator=(const NonnullRefPtr&) = delete; + template + NonnullOwnPtr& operator=(const WeakPtr&) = delete; + + RETURN_TYPESTATE(unconsumed) + NonnullOwnPtr& operator=(NonnullOwnPtr&& other) + { + if (this != &other) { + delete m_ptr; + m_ptr = other.leak_ptr(); + ASSERT(m_ptr); + } + return *this; + } + + template + RETURN_TYPESTATE(unconsumed) + NonnullOwnPtr& operator=(NonnullOwnPtr&& other) + { + if (this != static_cast(&other)) { + delete m_ptr; + m_ptr = other.leak_ptr(); + ASSERT(m_ptr); + } + return *this; + } + + CALLABLE_WHEN(unconsumed) + SET_TYPESTATE(consumed) + T* leak_ptr() + { + return exchange(m_ptr, nullptr); + } + + CALLABLE_WHEN(unconsumed) + T* ptr() { return m_ptr; } + CALLABLE_WHEN(unconsumed) + const T* ptr() const { return m_ptr; } + + CALLABLE_WHEN(unconsumed) + T* operator->() { return m_ptr; } + CALLABLE_WHEN(unconsumed) + const T* operator->() const { return m_ptr; } + + CALLABLE_WHEN(unconsumed) + T& operator*() { return *m_ptr; } + CALLABLE_WHEN(unconsumed) + const T& operator*() const { return *m_ptr; } + + CALLABLE_WHEN(unconsumed) + operator const T*() const { return m_ptr; } + CALLABLE_WHEN(unconsumed) + operator T*() { return m_ptr; } + +private: + void clear() + { + if (!m_ptr) + return; + delete m_ptr; + m_ptr = nullptr; + } + + T* m_ptr = nullptr; +}; + +template +inline NonnullOwnPtr +make(Args&&... args) +{ + return NonnullOwnPtr(NonnullOwnPtr::Adopt, *new T(forward(args)...)); +} + +template +struct Traits> : public GenericTraits> { + static unsigned hash(const NonnullOwnPtr& p) { return (unsigned)p.ptr(); } + static void dump(const NonnullOwnPtr& p) { kprintf("%p", p.ptr()); } + static bool equals(const NonnullOwnPtr& a, const NonnullOwnPtr& b) { return a.ptr() == b.ptr(); } +}; + +template +inline const LogStream& operator<<(const LogStream& stream, const NonnullOwnPtr& value) +{ + return stream << value.ptr(); +} + +} + +using AK::make; +using AK::NonnullOwnPtr; diff --git a/AK/OwnPtr.h b/AK/OwnPtr.h index ba93fd63b32..874f468751a 100644 --- a/AK/OwnPtr.h +++ b/AK/OwnPtr.h @@ -1,19 +1,9 @@ #pragma once -#include -#include -#include -#include +#include namespace AK { -template -class RefPtr; -template -class NonnullRefPtr; -template -class WeakPtr; - template class OwnPtr { public: @@ -26,6 +16,12 @@ public: : m_ptr(other.leak_ptr()) { } + + template + OwnPtr(NonnullOwnPtr&& other) + : m_ptr(static_cast(other.leak_ptr())) + { + } template OwnPtr(OwnPtr&& other) : m_ptr(static_cast(other.leak_ptr())) @@ -43,6 +39,13 @@ public: #endif } + OwnPtr(const OwnPtr&) = delete; + template + OwnPtr(const OwnPtr&) = delete; + OwnPtr& operator=(const OwnPtr&) = delete; + template + OwnPtr& operator=(const OwnPtr&) = delete; + template OwnPtr(const RefPtr&) = delete; template @@ -75,6 +78,15 @@ public: return *this; } + template + OwnPtr& operator=(NonnullOwnPtr&& other) + { + ASSERT(m_ptr != other.ptr()); + delete m_ptr; + m_ptr = other.leak_ptr(); + return *this; + } + OwnPtr& operator=(T* ptr) { if (m_ptr != ptr) @@ -99,9 +111,9 @@ public: T* leak_ptr() { - T* leakedPtr = m_ptr; + T* leaked_ptr = m_ptr; m_ptr = nullptr; - return leakedPtr; + return leaked_ptr; } T* ptr() { return m_ptr; } @@ -122,13 +134,6 @@ private: T* m_ptr = nullptr; }; -template -inline OwnPtr -make(Args&&... args) -{ - return OwnPtr(new T(AK::forward(args)...)); -} - template struct Traits> : public GenericTraits> { static unsigned hash(const OwnPtr& p) { return (unsigned)p.ptr(); } @@ -144,5 +149,4 @@ inline const LogStream& operator<<(const LogStream& stream, const OwnPtr& val } -using AK::make; using AK::OwnPtr;