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
|
|
|
|
2023-02-01 19:29:13 +01: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
|
|
|
}
|