openmohaa/code/qcommon/safeptr.h

299 lines
6.2 KiB
C
Raw Permalink Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
2025-01-31 20:31:16 +01:00
Copyright (C) 2025 the OpenMoHAA team
2016-03-27 11:49:47 +02:00
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// safeptr.h: Safe Pointers
2025-01-31 21:09:12 +01:00
#pragma once
2016-03-27 11:49:47 +02:00
#include "Linklist.h"
2023-01-29 20:59:31 +01:00
2025-01-31 21:09:12 +01:00
#include <utility>
2016-03-27 11:49:47 +02:00
class SafePtrBase
{
private:
2025-01-31 20:31:16 +01:00
void AddReference(Class *ptr);
void RemoveReference(Class *ptr);
2016-03-27 11:49:47 +02:00
protected:
2025-01-31 20:31:16 +01:00
SafePtrBase *prev;
SafePtrBase *next;
Class *ptr;
2016-03-27 11:49:47 +02:00
public:
2025-01-31 20:31:16 +01:00
SafePtrBase();
virtual ~SafePtrBase();
void InitSafePtr(Class *newptr);
Class *Pointer(void);
void Clear(void);
2025-01-31 21:09:12 +01:00
protected:
void Move(SafePtrBase&& other);
2016-03-27 11:49:47 +02:00
};
2025-01-31 20:31:16 +01:00
inline void SafePtrBase::AddReference(Class *ptr)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
if (!ptr->SafePtrList) {
ptr->SafePtrList = this;
LL_Reset(this, next, prev);
} else {
LL_Add(ptr->SafePtrList, this, next, prev);
}
2016-03-27 11:49:47 +02:00
}
2025-01-31 20:31:16 +01:00
inline void SafePtrBase::RemoveReference(Class *ptr)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
if (ptr->SafePtrList == this) {
if (ptr->SafePtrList->next == this) {
ptr->SafePtrList = nullptr;
} else {
ptr->SafePtrList = next;
LL_Remove(this, next, prev);
}
} else {
LL_Remove(this, next, prev);
}
2016-03-27 11:49:47 +02:00
}
2025-01-31 20:31:16 +01:00
inline void SafePtrBase::Clear(void)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
if (ptr) {
RemoveReference(ptr);
ptr = nullptr;
}
2016-03-27 11:49:47 +02:00
}
inline SafePtrBase::SafePtrBase()
{
2025-01-31 20:31:16 +01:00
prev = nullptr;
next = nullptr;
ptr = nullptr;
2016-03-27 11:49:47 +02:00
}
inline SafePtrBase::~SafePtrBase()
{
2025-01-31 20:31:16 +01:00
Clear();
2016-03-27 11:49:47 +02:00
}
2025-01-31 20:31:16 +01:00
inline Class *SafePtrBase::Pointer(void)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return ptr;
2016-03-27 11:49:47 +02:00
}
2025-01-31 20:31:16 +01:00
inline void SafePtrBase::InitSafePtr(Class *newptr)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
if (ptr != newptr) {
if (ptr) {
RemoveReference(ptr);
}
2016-03-27 11:49:47 +02:00
2025-01-31 20:31:16 +01:00
ptr = newptr;
if (ptr == nullptr) {
return;
}
2016-03-27 11:49:47 +02:00
2025-01-31 20:31:16 +01:00
AddReference(ptr);
}
2016-03-27 11:49:47 +02:00
}
2025-01-31 21:09:12 +01:00
inline void SafePtrBase::Move(SafePtrBase&& other)
{
prev = other.prev;
next = other.next;
ptr = other.ptr;
if (ptr && ptr->SafePtrList) {
if (ptr->SafePtrList == &other) {
ptr->SafePtrList = this;
} else {
if (ptr->SafePtrList->prev == &other) {
ptr->SafePtrList->prev = this;
}
if (ptr->SafePtrList->next == &other) {
ptr->SafePtrList->next = this;
}
}
}
if (prev) {
if (prev == &other) {
prev = this;
} else {
assert(prev->next == &other || prev->next == this);
prev->next = this;
}
}
if (next) {
if (next == &other) {
next = this;
} else {
assert(next->prev == &other || next->prev == this);
next->prev = this;
}
}
other.next = other.prev = NULL;
other.ptr = NULL;
}
2016-03-27 11:49:47 +02:00
template<class T>
class SafePtr : public SafePtrBase
{
public:
2025-01-31 20:31:16 +01:00
SafePtr(T *objptr = 0);
SafePtr(const SafePtr& obj);
2025-01-31 21:09:12 +01:00
SafePtr(SafePtr&& obj);
2016-03-27 11:49:47 +02:00
2025-01-31 20:31:16 +01:00
SafePtr& operator=(const SafePtr& obj);
SafePtr& operator=(T *const obj);
2025-01-31 21:09:12 +01:00
SafePtr& operator=(SafePtr&& obj);
2016-03-27 11:49:47 +02:00
#ifdef LINUX
2025-01-31 20:31:16 +01:00
friend bool operator== <>(SafePtr<T> a, T *b);
friend bool operator!= <>(SafePtr<T> a, T *b);
friend bool operator== <>(T *a, SafePtr<T> b);
friend bool operator!= <>(T *a, SafePtr<T> b);
friend bool operator== <>(SafePtr<T> a, SafePtr<T> b);
friend bool operator!= <>(SafePtr<T> a, SafePtr<T> b);
2016-03-27 11:49:47 +02:00
#else
2025-01-31 20:31:16 +01:00
// The compiler/linker gets confused when the friend functions definition are not templated
template<class U>
friend bool operator==(SafePtr<U> a, U *b);
template<class U>
friend bool operator!=(SafePtr<U> a, U *b);
template<class U>
friend bool operator==(U *a, SafePtr<U> b);
template<class U>
friend bool operator!=(U *a, SafePtr<U> b);
template<class U>
friend bool operator==(SafePtr<U> a, SafePtr<U> b);
template<class U>
friend bool operator!=(SafePtr<U> a, SafePtr<U> b);
2016-03-27 11:49:47 +02:00
#endif
2025-01-31 20:31:16 +01:00
bool operator!() const;
operator T *() const;
T *operator->() const;
T& operator*() const;
2016-03-27 11:49:47 +02:00
};
template<class T>
2025-01-31 20:31:16 +01:00
inline SafePtr<T>::SafePtr(T *objptr)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
InitSafePtr((Class *)objptr);
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline SafePtr<T>::SafePtr(const SafePtr& obj)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
InitSafePtr(obj.ptr);
2016-03-27 11:49:47 +02:00
}
2025-01-31 21:09:12 +01:00
template<class T>
inline SafePtr<T>::SafePtr(SafePtr&& obj)
{
Move(std::move(obj));
}
2016-03-27 11:49:47 +02:00
template<class T>
2025-01-31 20:31:16 +01:00
inline SafePtr<T>& SafePtr<T>::operator=(const SafePtr& obj)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
InitSafePtr(obj.ptr);
return *this;
2016-03-27 11:49:47 +02:00
}
2025-01-31 21:09:12 +01:00
template<class T>
inline SafePtr<T>& SafePtr<T>::operator=(SafePtr&& obj)
{
Clear();
Move(std::move(obj));
return *this;
}
2016-03-27 11:49:47 +02:00
template<class T>
2025-01-31 20:31:16 +01:00
inline SafePtr<T>& SafePtr<T>::operator=(T *const obj)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
InitSafePtr(obj);
return *this;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator==(SafePtr<T> a, T *b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a.ptr == b;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator!=(SafePtr<T> a, T *b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a.ptr != b;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator==(T *a, SafePtr<T> b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a == b.ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator!=(T *a, SafePtr<T> b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a != b.ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator==(SafePtr<T> a, SafePtr<T> b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a.ptr == b.ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool operator!=(SafePtr<T> a, SafePtr<T> b)
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return a.ptr != b.ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline bool SafePtr<T>::operator!() const
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return ptr == nullptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline SafePtr<T>::operator T *() const
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return (T *)ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline T *SafePtr<T>::operator->() const
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return (T *)ptr;
2016-03-27 11:49:47 +02:00
}
template<class T>
2025-01-31 20:31:16 +01:00
inline T& SafePtr<T>::operator*() const
2016-03-27 11:49:47 +02:00
{
2025-01-31 20:31:16 +01:00
return *(T *)ptr;
2016-03-27 11:49:47 +02:00
}