Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
246
libs/drape/pointers.hpp
Normal file
246
libs/drape/pointers.hpp
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
#pragma once
|
||||
|
||||
#include "drape/drape_diagnostics.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
// This class tracks usage of drape_ptr's and ref_ptr's
|
||||
class DpPointerTracker
|
||||
{
|
||||
public:
|
||||
typedef std::map<void *, std::pair<int, std::string>> TAlivePointers;
|
||||
|
||||
static DpPointerTracker & Instance();
|
||||
|
||||
template <typename T>
|
||||
void RefPtr(T * refPtr)
|
||||
{
|
||||
RefPtrNamed(static_cast<void *>(refPtr), typeid(refPtr).name());
|
||||
}
|
||||
|
||||
void DerefPtr(void * p);
|
||||
|
||||
void DestroyPtr(void * p);
|
||||
|
||||
TAlivePointers const & GetAlivePointers() const;
|
||||
|
||||
private:
|
||||
DpPointerTracker() = default;
|
||||
~DpPointerTracker();
|
||||
|
||||
void RefPtrNamed(void * refPtr, std::string const & name);
|
||||
|
||||
TAlivePointers m_alivePointers;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
// Custom deleter for unique_ptr
|
||||
class DpPointerDeleter
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
void operator()(T * p)
|
||||
{
|
||||
DpPointerTracker::Instance().DestroyPtr(p);
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using drape_ptr = std::unique_ptr<T, DpPointerDeleter>;
|
||||
#else
|
||||
template <typename T>
|
||||
using drape_ptr = std::unique_ptr<T>;
|
||||
#endif
|
||||
|
||||
template <typename T, typename... Args>
|
||||
drape_ptr<T> make_unique_dp(Args &&... args)
|
||||
{
|
||||
return drape_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class ref_ptr
|
||||
{
|
||||
public:
|
||||
ref_ptr() noexcept : m_ptr(nullptr)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
ref_ptr(T * ptr, bool isOwnerUnique = false) noexcept
|
||||
#else
|
||||
ref_ptr(T * ptr) noexcept
|
||||
#endif
|
||||
: m_ptr(ptr)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = isOwnerUnique;
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().RefPtr(m_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
ref_ptr(ref_ptr const & rhs) noexcept : m_ptr(rhs.m_ptr)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = rhs.m_isOwnerUnique;
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().RefPtr(m_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
ref_ptr(ref_ptr && rhs) noexcept
|
||||
{
|
||||
m_ptr = rhs.m_ptr;
|
||||
rhs.m_ptr = nullptr;
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = rhs.m_isOwnerUnique;
|
||||
rhs.m_isOwnerUnique = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
~ref_ptr()
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().DerefPtr(m_ptr);
|
||||
#endif
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
T * operator->() const { return m_ptr; }
|
||||
|
||||
template <typename TResult>
|
||||
operator ref_ptr<TResult>() const
|
||||
{
|
||||
TResult * res;
|
||||
|
||||
if constexpr (std::is_base_of<TResult, T>::value || std::is_void<TResult>::value)
|
||||
res = m_ptr;
|
||||
else
|
||||
{
|
||||
/// @todo I'd prefer separate down_cast<ref_ptr<TResult>> function, but the codebase already relies on it.
|
||||
static_assert(std::is_base_of<T, TResult>::value);
|
||||
res = static_cast<TResult *>(m_ptr);
|
||||
ASSERT_EQUAL(dynamic_cast<TResult *>(m_ptr), res, ("Avoid multiple inheritance"));
|
||||
}
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
return ref_ptr<TResult>(res, m_isOwnerUnique);
|
||||
#else
|
||||
return ref_ptr<TResult>(res);
|
||||
#endif
|
||||
}
|
||||
|
||||
explicit operator bool() const { return m_ptr != nullptr; }
|
||||
|
||||
bool operator==(ref_ptr const & rhs) const { return m_ptr == rhs.m_ptr; }
|
||||
|
||||
bool operator==(T * rhs) const { return m_ptr == rhs; }
|
||||
|
||||
bool operator!=(ref_ptr const & rhs) const { return !operator==(rhs); }
|
||||
|
||||
bool operator!=(T * rhs) const { return !operator==(rhs); }
|
||||
|
||||
bool operator<(ref_ptr const & rhs) const { return m_ptr < rhs.m_ptr; }
|
||||
|
||||
template <typename TResult, typename = std::enable_if_t<!std::is_void<TResult>::value>>
|
||||
TResult & operator*() const
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
ref_ptr & operator=(ref_ptr const & rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().DerefPtr(m_ptr);
|
||||
#endif
|
||||
|
||||
m_ptr = rhs.m_ptr;
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = rhs.m_isOwnerUnique;
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().RefPtr(m_ptr);
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ref_ptr & operator=(ref_ptr && rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
if (m_isOwnerUnique)
|
||||
DpPointerTracker::Instance().DerefPtr(m_ptr);
|
||||
#endif
|
||||
|
||||
m_ptr = rhs.m_ptr;
|
||||
rhs.m_ptr = nullptr;
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
m_isOwnerUnique = rhs.m_isOwnerUnique;
|
||||
rhs.m_isOwnerUnique = false;
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
T * get() const { return m_ptr; }
|
||||
|
||||
private:
|
||||
T * m_ptr;
|
||||
#if defined(TRACK_POINTERS)
|
||||
bool m_isOwnerUnique;
|
||||
#endif
|
||||
|
||||
template <typename TResult>
|
||||
friend inline std::string DebugPrint(ref_ptr<TResult> const & v);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline std::string DebugPrint(ref_ptr<T> const & v)
|
||||
{
|
||||
return DebugPrint(v.m_ptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ref_ptr<T> make_ref(drape_ptr<T> const & drapePtr)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
return ref_ptr<T>(drapePtr.get(), true /* isOwnerUnique */);
|
||||
#else
|
||||
return ref_ptr<T>(drapePtr.get());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ref_ptr<T> make_ref(T * ptr)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
return ref_ptr<T>(ptr, false /* isOwnerUnique */);
|
||||
#else
|
||||
return ref_ptr<T>(ptr);
|
||||
#endif
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue