ladybird/AK/RetainPtr.h
Andreas Kling 10c470e95f Make page_in_from_vnode 2x faster.
...by adding a new class called Ext2Inode that inherits CoreInode.
The idea is that a vnode will wrap a CoreInode rather than InodeIdentifier.
Each CoreInode subclass can keep whatever caches they like.

Right now, Ext2Inode caches the list of block indices since it can be very
expensive to retrieve.
2018-11-13 13:02:39 +01:00

142 lines
3.2 KiB
C++

#pragma once
#include "Compiler.h"
#include "Types.h"
namespace AK {
template<typename T>
inline void retainIfNotNull(T* ptr)
{
if (ptr)
ptr->retain();
}
template<typename T>
inline void releaseIfNotNull(T* ptr)
{
if (ptr)
ptr->release();
}
template<typename T>
class RetainPtr {
public:
enum AdoptTag { Adopt };
RetainPtr() { }
RetainPtr(const T* ptr) : m_ptr(const_cast<T*>(ptr)) { retainIfNotNull(m_ptr); }
RetainPtr(T* ptr) : m_ptr(ptr) { retainIfNotNull(m_ptr); }
RetainPtr(T& object) : m_ptr(&object) { m_ptr->retain(); }
RetainPtr(AdoptTag, T& object) : m_ptr(&object) { }
RetainPtr(RetainPtr& other) : m_ptr(other.copyRef().leakRef()) { }
RetainPtr(RetainPtr&& other) : m_ptr(other.leakRef()) { }
template<typename U> RetainPtr(RetainPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakRef())) { }
RetainPtr(const RetainPtr& other) : m_ptr(const_cast<RetainPtr&>(other).copyRef().leakRef()) { }
template<typename U> RetainPtr(const RetainPtr<U>& other) : m_ptr(const_cast<RetainPtr<U>&>(other).copyRef().leakRef()) { }
~RetainPtr()
{
clear();
#ifdef SANITIZE_PTRS
if constexpr(sizeof(T*) == 8)
m_ptr = (T*)(0xe0e0e0e0e0e0e0e0);
else
m_ptr = (T*)(0xe0e0e0e0);
#endif
}
RetainPtr(std::nullptr_t) { }
RetainPtr& operator=(RetainPtr&& other)
{
if (this != &other) {
releaseIfNotNull(m_ptr);
m_ptr = other.leakRef();
}
return *this;
}
template<typename U>
RetainPtr& operator=(RetainPtr<U>&& other)
{
if (this != static_cast<void*>(&other)) {
releaseIfNotNull(m_ptr);
m_ptr = other.leakRef();
}
return *this;
}
RetainPtr& operator=(T* ptr)
{
if (m_ptr != ptr)
releaseIfNotNull(m_ptr);
m_ptr = ptr;
retainIfNotNull(m_ptr);
return *this;
}
RetainPtr& operator=(T& object)
{
if (m_ptr != &object)
releaseIfNotNull(m_ptr);
m_ptr = &object;
retainIfNotNull(m_ptr);
return *this;
}
RetainPtr& operator=(std::nullptr_t)
{
clear();
return *this;
}
RetainPtr copyRef() const
{
return RetainPtr(m_ptr);
}
void clear()
{
releaseIfNotNull(m_ptr);
m_ptr = nullptr;
}
bool operator!() const { return !m_ptr; }
typedef T* RetainPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : nullptr; }
T* leakRef()
{
T* leakedPtr = m_ptr;
m_ptr = nullptr;
return leakedPtr;
}
T* ptr() { return m_ptr; }
const T* ptr() const { return m_ptr; }
T* operator->() { return m_ptr; }
const T* operator->() const { return m_ptr; }
T& operator*() { return *m_ptr; }
const T& operator*() const { return *m_ptr; }
operator bool() { return !!m_ptr; }
bool is_null() const { return !m_ptr; }
private:
T* m_ptr = nullptr;
};
template<typename T>
inline RetainPtr<T> adopt(T& object)
{
return RetainPtr<T>(RetainPtr<T>::Adopt, object);
}
}
using AK::RetainPtr;
using AK::adopt;