2008-03-28 06:03:59 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* This program 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 this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2014-02-18 01:34:18 +00:00
|
|
|
*
|
2008-03-28 06:03:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef COMMON_PTR_H
|
|
|
|
#define COMMON_PTR_H
|
|
|
|
|
|
|
|
#include "common/scummsys.h"
|
2010-03-20 20:01:44 +00:00
|
|
|
#include "common/noncopyable.h"
|
2017-10-06 01:33:45 +00:00
|
|
|
#include "common/safe-bool.h"
|
2011-08-06 14:30:52 +00:00
|
|
|
#include "common/types.h"
|
2008-03-28 06:03:59 +00:00
|
|
|
|
|
|
|
namespace Common {
|
|
|
|
|
2008-03-29 20:14:32 +00:00
|
|
|
class SharedPtrDeletionInternal {
|
|
|
|
public:
|
|
|
|
virtual ~SharedPtrDeletionInternal() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
class SharedPtrDeletionImpl : public SharedPtrDeletionInternal {
|
|
|
|
public:
|
|
|
|
SharedPtrDeletionImpl(T *ptr) : _ptr(ptr) {}
|
|
|
|
~SharedPtrDeletionImpl() {
|
2017-11-18 05:28:15 +00:00
|
|
|
STATIC_ASSERT(sizeof(T) > 0, SharedPtr_cannot_delete_incomplete_type);
|
2008-03-29 20:14:32 +00:00
|
|
|
delete _ptr;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
T *_ptr;
|
|
|
|
};
|
|
|
|
|
2008-03-30 01:26:51 +00:00
|
|
|
template<class T, class D>
|
|
|
|
class SharedPtrDeletionDeleterImpl : public SharedPtrDeletionInternal {
|
|
|
|
public:
|
|
|
|
SharedPtrDeletionDeleterImpl(T *ptr, D d) : _ptr(ptr), _deleter(d) {}
|
|
|
|
~SharedPtrDeletionDeleterImpl() { _deleter(_ptr); }
|
|
|
|
private:
|
|
|
|
T *_ptr;
|
|
|
|
D _deleter;
|
|
|
|
};
|
|
|
|
|
2008-03-28 06:03:59 +00:00
|
|
|
/**
|
|
|
|
* A simple shared pointer implementation modelled after boost.
|
|
|
|
*
|
|
|
|
* This object keeps track of the assigned pointer and automatically
|
|
|
|
* frees it when no more SharedPtr references to it exist.
|
|
|
|
*
|
|
|
|
* To achieve that the object implements an internal reference counting.
|
|
|
|
* Thus you should try to avoid using the plain pointer after assigning
|
|
|
|
* it to a SharedPtr object for the first time. If you still use the
|
2008-12-22 11:22:15 +00:00
|
|
|
* plain pointer be sure you do not delete it on your own. You may also
|
2008-03-28 06:03:59 +00:00
|
|
|
* not use the plain pointer to create a new SharedPtr object, since that
|
|
|
|
* would result in a double deletion of the pointer sooner or later.
|
|
|
|
*
|
|
|
|
* Example creation:
|
|
|
|
* Common::SharedPtr<int> pointer(new int(1));
|
|
|
|
* would create a pointer to int. Later on usage via *pointer is the same
|
|
|
|
* as for a normal pointer. If you need to access the plain pointer value
|
|
|
|
* itself later on use the get method. The class also supplies a operator
|
|
|
|
* ->, which does the same as the -> operator on a normal pointer.
|
|
|
|
*
|
|
|
|
* Be sure you are using new to initialize the pointer you want to manage.
|
2008-03-30 01:26:51 +00:00
|
|
|
* If you do not use new for allocating, you have to supply a deleter as
|
|
|
|
* second parameter when creating a SharedPtr object. The deleter has to
|
|
|
|
* implement operator() which takes the pointer it should free as argument.
|
2008-03-28 06:03:59 +00:00
|
|
|
*
|
|
|
|
* Note that you have to specify the type itself not the pointer type as
|
2008-03-29 20:14:32 +00:00
|
|
|
* template parameter.
|
|
|
|
*
|
|
|
|
* When creating a SharedPtr object from a normal pointer you need a real
|
|
|
|
* definition of the type you want SharedPtr to manage, a simple forward
|
|
|
|
* definition is not enough.
|
2008-03-28 06:03:59 +00:00
|
|
|
*
|
|
|
|
* The class has implicit upcast support, so if you got a class B derived
|
|
|
|
* from class A, you can assign a pointer to B without any problems to a
|
2008-12-22 11:22:15 +00:00
|
|
|
* SharedPtr object with template parameter A. The very same applies to
|
2008-03-29 00:08:56 +00:00
|
|
|
* assignment of a SharedPtr<B> object to a SharedPtr<A> object.
|
2008-03-28 06:03:59 +00:00
|
|
|
*
|
|
|
|
* There are also operators != and == to compare two SharedPtr objects
|
2008-03-30 18:32:42 +00:00
|
|
|
* with compatible pointers. Comparison between a SharedPtr object and
|
|
|
|
* a plain pointer is only possible via SharedPtr::get.
|
2008-03-28 06:03:59 +00:00
|
|
|
*/
|
|
|
|
template<class T>
|
2017-10-06 01:33:45 +00:00
|
|
|
class SharedPtr : public SafeBool<SharedPtr<T> > {
|
2012-03-17 21:02:16 +00:00
|
|
|
#if !defined(__GNUC__) || GCC_ATLEAST(3, 0)
|
2008-03-30 01:09:05 +00:00
|
|
|
template<class T2> friend class SharedPtr;
|
|
|
|
#endif
|
2008-03-28 06:03:59 +00:00
|
|
|
public:
|
|
|
|
typedef int RefValue;
|
|
|
|
typedef T ValueType;
|
2010-03-20 20:25:12 +00:00
|
|
|
typedef T *PointerType;
|
|
|
|
typedef T &ReferenceType;
|
2008-03-28 06:03:59 +00:00
|
|
|
|
2018-04-05 18:25:28 +00:00
|
|
|
SharedPtr() : _refCount(nullptr), _deletion(nullptr), _pointer(nullptr) {}
|
2010-03-20 20:16:16 +00:00
|
|
|
|
|
|
|
template<class T2>
|
|
|
|
explicit SharedPtr(T2 *p) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionImpl<T2>(p)), _pointer(p) {}
|
|
|
|
|
|
|
|
template<class T2, class D>
|
|
|
|
SharedPtr(T2 *p, D d) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionDeleterImpl<T2, D>(p, d)), _pointer(p) {}
|
2008-03-28 06:03:59 +00:00
|
|
|
|
2008-03-29 20:14:32 +00:00
|
|
|
SharedPtr(const SharedPtr &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
|
2010-03-20 20:16:16 +00:00
|
|
|
template<class T2>
|
|
|
|
SharedPtr(const SharedPtr<T2> &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
|
2008-03-28 06:03:59 +00:00
|
|
|
|
|
|
|
~SharedPtr() { decRef(); }
|
|
|
|
|
2008-07-29 09:23:54 +00:00
|
|
|
SharedPtr &operator=(const SharedPtr &r) {
|
2008-03-28 06:03:59 +00:00
|
|
|
if (r._refCount)
|
|
|
|
++(*r._refCount);
|
|
|
|
decRef();
|
|
|
|
|
|
|
|
_refCount = r._refCount;
|
2008-03-29 20:14:32 +00:00
|
|
|
_deletion = r._deletion;
|
2008-03-28 06:03:59 +00:00
|
|
|
_pointer = r._pointer;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T2>
|
2008-07-29 09:23:54 +00:00
|
|
|
SharedPtr &operator=(const SharedPtr<T2> &r) {
|
2008-03-28 06:03:59 +00:00
|
|
|
if (r._refCount)
|
|
|
|
++(*r._refCount);
|
|
|
|
decRef();
|
|
|
|
|
|
|
|
_refCount = r._refCount;
|
2008-03-29 20:14:32 +00:00
|
|
|
_deletion = r._deletion;
|
2008-03-28 06:03:59 +00:00
|
|
|
_pointer = r._pointer;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-03-20 20:25:12 +00:00
|
|
|
ReferenceType operator*() const { assert(_pointer); return *_pointer; }
|
|
|
|
PointerType operator->() const { assert(_pointer); return _pointer; }
|
2008-03-28 06:03:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the plain pointer value. Be sure you know what you
|
|
|
|
* do if you are continuing to use that pointer.
|
|
|
|
*
|
|
|
|
* @return the pointer the SharedPtr object manages
|
|
|
|
*/
|
2010-03-20 20:25:12 +00:00
|
|
|
PointerType get() const { return _pointer; }
|
2008-03-28 06:03:59 +00:00
|
|
|
|
2008-03-29 00:08:56 +00:00
|
|
|
/**
|
|
|
|
* Implicit conversion operator to bool for convenience, to make
|
2008-03-30 18:32:42 +00:00
|
|
|
* checks like "if (sharedPtr) ..." possible.
|
2008-03-29 00:08:56 +00:00
|
|
|
*/
|
2017-10-06 01:33:45 +00:00
|
|
|
bool operator_bool() const { return _pointer != nullptr; }
|
2008-03-28 06:03:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the SharedPtr object is the only object refering
|
|
|
|
* to the assigned pointer. This should just be used for
|
|
|
|
* debugging purposes.
|
|
|
|
*/
|
|
|
|
bool unique() const { return refCount() == 1; }
|
|
|
|
|
2008-07-29 09:16:53 +00:00
|
|
|
/**
|
|
|
|
* Resets the SharedPtr object to a NULL pointer.
|
|
|
|
*/
|
|
|
|
void reset() {
|
|
|
|
decRef();
|
2018-06-04 10:36:18 +00:00
|
|
|
_deletion = nullptr;
|
|
|
|
_refCount = nullptr;
|
|
|
|
_pointer = nullptr;
|
2008-07-29 09:16:53 +00:00
|
|
|
}
|
|
|
|
|
2010-01-24 12:19:09 +00:00
|
|
|
template<class T2>
|
2011-08-06 07:47:19 +00:00
|
|
|
bool operator==(const SharedPtr<T2> &r) const {
|
2010-01-24 12:19:09 +00:00
|
|
|
return _pointer == r.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T2>
|
2011-08-06 07:47:19 +00:00
|
|
|
bool operator!=(const SharedPtr<T2> &r) const {
|
2010-01-24 12:19:09 +00:00
|
|
|
return _pointer != r.get();
|
|
|
|
}
|
2009-02-26 13:54:21 +00:00
|
|
|
|
2008-03-28 06:03:59 +00:00
|
|
|
/**
|
|
|
|
* Returns the number of references to the assigned pointer.
|
|
|
|
* This should just be used for debugging purposes.
|
|
|
|
*/
|
|
|
|
RefValue refCount() const { return _refCount ? *_refCount : 0; }
|
2012-03-17 21:02:16 +00:00
|
|
|
#if !defined(__GNUC__) || GCC_ATLEAST(3, 0)
|
2008-03-28 06:03:59 +00:00
|
|
|
private:
|
2008-04-07 21:07:07 +00:00
|
|
|
#endif
|
2008-03-28 06:03:59 +00:00
|
|
|
void decRef() {
|
|
|
|
if (_refCount) {
|
|
|
|
--(*_refCount);
|
|
|
|
if (!*_refCount) {
|
|
|
|
delete _refCount;
|
2008-03-29 20:14:32 +00:00
|
|
|
delete _deletion;
|
2018-04-05 18:25:28 +00:00
|
|
|
_deletion = nullptr;
|
|
|
|
_refCount = nullptr;
|
|
|
|
_pointer = nullptr;
|
2008-03-28 06:03:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RefValue *_refCount;
|
2008-03-29 20:14:32 +00:00
|
|
|
SharedPtrDeletionInternal *_deletion;
|
2010-03-20 20:25:12 +00:00
|
|
|
PointerType _pointer;
|
2008-03-28 06:03:59 +00:00
|
|
|
};
|
|
|
|
|
2017-11-18 05:28:15 +00:00
|
|
|
template <typename T>
|
|
|
|
struct DefaultDeleter {
|
|
|
|
inline void operator()(T *object) {
|
|
|
|
STATIC_ASSERT(sizeof(T) > 0, cannot_delete_incomplete_type);
|
|
|
|
delete object;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, class D = DefaultDeleter<T> >
|
|
|
|
class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T, D> > {
|
2010-03-20 20:01:44 +00:00
|
|
|
public:
|
|
|
|
typedef T ValueType;
|
|
|
|
typedef T *PointerType;
|
2010-03-20 20:25:12 +00:00
|
|
|
typedef T &ReferenceType;
|
2010-03-20 20:01:44 +00:00
|
|
|
|
2018-06-04 10:36:18 +00:00
|
|
|
explicit ScopedPtr(PointerType o = nullptr) : _pointer(o) {}
|
2010-03-20 20:01:44 +00:00
|
|
|
|
2010-03-20 20:25:12 +00:00
|
|
|
ReferenceType operator*() const { return *_pointer; }
|
2010-03-20 20:16:16 +00:00
|
|
|
PointerType operator->() const { return _pointer; }
|
2010-03-20 20:01:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Implicit conversion operator to bool for convenience, to make
|
|
|
|
* checks like "if (scopedPtr) ..." possible.
|
|
|
|
*/
|
2017-10-06 01:33:45 +00:00
|
|
|
bool operator_bool() const { return _pointer != nullptr; }
|
2010-03-20 20:01:44 +00:00
|
|
|
|
2010-07-21 18:17:51 +00:00
|
|
|
~ScopedPtr() {
|
2017-11-18 05:28:15 +00:00
|
|
|
D()(_pointer);
|
2010-03-20 20:01:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resets the pointer with the new value. Old object will be destroyed
|
|
|
|
*/
|
2018-06-04 10:36:18 +00:00
|
|
|
void reset(PointerType o = nullptr) {
|
2017-11-18 05:28:15 +00:00
|
|
|
D()(_pointer);
|
2010-03-20 20:16:16 +00:00
|
|
|
_pointer = o;
|
2010-03-20 20:01:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-07-21 18:17:51 +00:00
|
|
|
* Returns the plain pointer value.
|
2010-03-20 20:01:44 +00:00
|
|
|
*
|
|
|
|
* @return the pointer the ScopedPtr manages
|
|
|
|
*/
|
2010-03-20 20:16:16 +00:00
|
|
|
PointerType get() const { return _pointer; }
|
2010-03-20 20:01:44 +00:00
|
|
|
|
|
|
|
/**
|
2010-07-21 18:17:51 +00:00
|
|
|
* Returns the plain pointer value and releases ScopedPtr.
|
2010-03-20 20:01:44 +00:00
|
|
|
* After release() call you need to delete object yourself
|
|
|
|
*
|
|
|
|
* @return the pointer the ScopedPtr manages
|
|
|
|
*/
|
2010-03-20 20:16:16 +00:00
|
|
|
PointerType release() {
|
|
|
|
PointerType r = _pointer;
|
2018-06-04 10:36:18 +00:00
|
|
|
_pointer = nullptr;
|
2010-03-20 20:01:44 +00:00
|
|
|
return r;
|
|
|
|
}
|
2010-03-20 20:16:16 +00:00
|
|
|
|
2010-11-04 00:49:12 +00:00
|
|
|
private:
|
2010-03-20 20:16:16 +00:00
|
|
|
PointerType _pointer;
|
2010-03-20 20:01:44 +00:00
|
|
|
};
|
|
|
|
|
2017-11-18 05:28:15 +00:00
|
|
|
template<typename T, class D = DefaultDeleter<T> >
|
|
|
|
class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T, D> > {
|
2011-08-06 14:30:52 +00:00
|
|
|
public:
|
|
|
|
typedef T ValueType;
|
|
|
|
typedef T *PointerType;
|
|
|
|
typedef T &ReferenceType;
|
|
|
|
|
|
|
|
explicit DisposablePtr(PointerType o, DisposeAfterUse::Flag dispose) : _pointer(o), _dispose(dispose) {}
|
|
|
|
|
|
|
|
~DisposablePtr() {
|
2017-11-18 05:28:15 +00:00
|
|
|
if (_dispose) D()(_pointer);
|
2011-08-06 14:30:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ReferenceType operator*() const { return *_pointer; }
|
|
|
|
PointerType operator->() const { return _pointer; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implicit conversion operator to bool for convenience, to make
|
|
|
|
* checks like "if (scopedPtr) ..." possible.
|
|
|
|
*/
|
2017-10-06 01:33:45 +00:00
|
|
|
bool operator_bool() const { return _pointer != nullptr; }
|
2011-08-06 14:30:52 +00:00
|
|
|
|
2017-12-28 18:47:45 +00:00
|
|
|
/**
|
|
|
|
* Resets the pointer with the new value. Old object will be destroyed
|
|
|
|
*/
|
|
|
|
void reset(PointerType o, DisposeAfterUse::Flag dispose) {
|
|
|
|
if (_dispose) D()(_pointer);
|
|
|
|
_pointer = o;
|
|
|
|
_dispose = dispose;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the pointer. Old object will be destroyed
|
|
|
|
*/
|
|
|
|
void reset() {
|
|
|
|
reset(nullptr, DisposeAfterUse::NO);
|
|
|
|
}
|
|
|
|
|
2011-08-06 14:30:52 +00:00
|
|
|
/**
|
|
|
|
* Returns the plain pointer value.
|
|
|
|
*
|
|
|
|
* @return the pointer the DisposablePtr manages
|
|
|
|
*/
|
|
|
|
PointerType get() const { return _pointer; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
PointerType _pointer;
|
|
|
|
DisposeAfterUse::Flag _dispose;
|
|
|
|
};
|
|
|
|
|
2009-10-04 21:26:33 +00:00
|
|
|
} // End of namespace Common
|
2008-03-28 06:03:59 +00:00
|
|
|
|
|
|
|
#endif
|