mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
137 lines
4.2 KiB
C++
137 lines
4.2 KiB
C++
//+----------------------------------------------------------------------------+
|
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
//+----------------------------------------------------------------------------+
|
|
|
|
#pragma once
|
|
|
|
/** @file util/smart_ptr.hpp
|
|
*
|
|
* @brief Smart pointers and related utility functions
|
|
*/
|
|
|
|
// ----------------------------------------------------------------------------- : Includes
|
|
|
|
#include <memory>
|
|
|
|
using std::shared_ptr;
|
|
using std::unique_ptr;
|
|
using std::static_pointer_cast;
|
|
using std::dynamic_pointer_cast;
|
|
using std::make_shared;
|
|
using std::make_unique;
|
|
|
|
#ifndef USE_INTRUSIVE_PTR
|
|
#define USE_INTRUSIVE_PTR 1
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------- : Intrusive pointers
|
|
|
|
#if USE_INTRUSIVE_PTR
|
|
|
|
#include <atomic>
|
|
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
|
using boost::intrusive_ptr;
|
|
|
|
/// Base class for types that can be pointed to
|
|
template <typename T> class IntrusivePtrBase {
|
|
public:
|
|
IntrusivePtrBase() {}
|
|
// don't copy or assign ref count
|
|
IntrusivePtrBase(IntrusivePtrBase const&) {}
|
|
void operator = (IntrusivePtrBase const&) {}
|
|
protected:
|
|
inline void destroy() const {
|
|
delete static_cast<const T*>(this);
|
|
}
|
|
private:
|
|
mutable std::atomic<unsigned int> ref_count = 0;
|
|
template <typename U> friend void intrusive_ptr_add_ref(const IntrusivePtrBase<U>* ptr);
|
|
template <typename U> friend void intrusive_ptr_release(const IntrusivePtrBase<U>* ptr);
|
|
};
|
|
|
|
template <typename T> void intrusive_ptr_add_ref(const IntrusivePtrBase<T>* ptr) {
|
|
++(ptr->ref_count);
|
|
}
|
|
|
|
template <typename T> void intrusive_ptr_release(const IntrusivePtrBase<T>* ptr) {
|
|
if (--(ptr->ref_count) == 0) {
|
|
static_cast<const T*>(ptr)->destroy();
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
class IntrusiveFromThis {
|
|
public:
|
|
inline intrusive_ptr<T> intrusive_from_this() noexcept {
|
|
return intrusive_ptr<T>(static_cast<T*>(this));
|
|
}
|
|
};
|
|
|
|
/// Allocate an object of type T and store it in a new intrusive_ptr, similar to std::make_shared
|
|
template <typename T, class... Args>
|
|
inline intrusive_ptr<T> make_intrusive(Args&&... args) {
|
|
return intrusive_ptr<T>(new T(std::forward<Args>(args)...));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : Shared pointers
|
|
#else
|
|
|
|
template <typename T> using intrusive_ptr = shared_ptr<T>;
|
|
|
|
/// Base class for types that can be pointed to
|
|
template <typename T> class IntrusivePtrBase {};
|
|
|
|
template <typename T>
|
|
class IntrusiveFromThis : public std::enable_shared_from_this<T> {
|
|
public:
|
|
inline intrusive_ptr<T> intrusive_from_this() {
|
|
return this->shared_from_this();
|
|
}
|
|
};
|
|
|
|
/// Allocate an object of type T and store it in a new intrusive_ptr, similar to std::make_shared
|
|
template <typename T, class... Args>
|
|
inline intrusive_ptr<T> make_intrusive(Args&&... args) {
|
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
|
}
|
|
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------- : Declaring
|
|
|
|
/// Declares the type TypeP as a intrusive_ptr<Type>
|
|
#define DECLARE_POINTER_TYPE(Type) \
|
|
class Type; \
|
|
typedef intrusive_ptr<Type> Type##P
|
|
|
|
/// Declares the type TypeP as a shared_ptr<Type>
|
|
#define DECLARE_SHARED_POINTER_TYPE(Type) \
|
|
class Type; \
|
|
typedef shared_ptr<Type> Type##P
|
|
|
|
// ----------------------------------------------------------------------------- : Utility
|
|
|
|
/// IntrusivePtrBase with a virtual destructor
|
|
class IntrusivePtrVirtualBase : public IntrusivePtrBase<IntrusivePtrVirtualBase> {
|
|
public:
|
|
virtual ~IntrusivePtrVirtualBase() {}
|
|
};
|
|
|
|
class IntrusivePtrBaseWithDelete : public IntrusivePtrBase<IntrusivePtrBaseWithDelete> {
|
|
public:
|
|
virtual ~IntrusivePtrBaseWithDelete() {}
|
|
protected:
|
|
/// Delete this object
|
|
virtual void destroy() const {
|
|
delete this;
|
|
}
|
|
template <typename T> friend void intrusive_ptr_release(const IntrusivePtrBase<T>* ptr);
|
|
};
|
|
|
|
/// Pointer to 'anything'
|
|
typedef intrusive_ptr<IntrusivePtrVirtualBase> VoidP;
|
|
|
|
|