#include <string>
#include <thread>
#include <iostream>
#include <type_traits>
#include <cxxabi.h>
#include <memory>
#define OPENVPN_RC_DEBUG
#if defined(_MSC_VER) && defined(_M_X64)
typedef long long olong;
typedef unsigned long long oulong;
#else
typedef long olong;
typedef unsigned long oulong;
#endif
inline std::string cxx_demangle(const char *mangled_name)
{
int status;
std::unique_ptr<char[]> realname;
realname.reset(abi::__cxa_demangle(mangled_name, 0, 0, &status));
if (!status)
return std::string(realname.get());
else
return "DEMANGLE_ERROR";
}
template <typename R>
inline void intrusive_ptr_add_ref(R *p) noexcept
{
#ifdef OPENVPN_RC_DEBUG
std::cout << "ADD REF " << cxx_demangle(typeid(p).name()) << std::endl;
#endif
++p->refcount_;
}
template <typename R>
inline void intrusive_ptr_release(R *p) noexcept
{
if (--p->refcount_ == 0)
{
#ifdef OPENVPN_RC_DEBUG
std::cout << "DEL OBJ " << cxx_demangle(typeid(p).name()) << std::endl;
#endif
delete p;
}
else
{
#ifdef OPENVPN_RC_DEBUG
std::cout << "REL REF " << cxx_demangle(typeid(p).name()) << std::endl;
#endif
}
}
class thread_unsafe_refcount
{
public:
thread_unsafe_refcount() noexcept
: rc(olong(0))
{
}
void operator++() noexcept
{
++rc;
}
olong operator--() noexcept
{
return --rc;
}
bool inc_if_nonzero() noexcept
{
if (rc)
{
++rc;
return true;
}
else
return false;
}
olong use_count() const noexcept
{
return rc;
}
static constexpr bool is_thread_safe()
{
return false;
}
private:
thread_unsafe_refcount(const thread_unsafe_refcount&) = delete;
thread_unsafe_refcount& operator=(const thread_unsafe_refcount&) = delete;
olong rc;
};
// The smart pointer class
template <typename T>
class RCPtr
{
public:
typedef T element_type;
RCPtr() noexcept
: px(nullptr)
{
}
RCPtr(T* p, const bool add_ref=true) noexcept
: px(p)
{
if (px && add_ref)
intrusive_ptr_add_ref(px);
}
RCPtr(const RCPtr& rhs) noexcept
: px(rhs.px)
{
if (px)
intrusive_ptr_add_ref(px);
}
RCPtr(RCPtr&& rhs) noexcept
: px(rhs.px)
{
rhs.px = nullptr;
}
template <typename U>
RCPtr(const RCPtr<U>& rhs) noexcept
: px(rhs.get())
{
if (px)
intrusive_ptr_add_ref(px);
}
~RCPtr()
{
if (px)
intrusive_ptr_release(px);
}
RCPtr& operator=(const RCPtr& rhs) noexcept
{
RCPtr(rhs).swap(*this);
return *this;
}
RCPtr& operator=(RCPtr&& rhs) noexcept
{
RCPtr(std::move(rhs)).swap(*this);
return *this;
}
void reset() noexcept
{
RCPtr().swap(*this);
}
void reset(T* rhs) noexcept
{
RCPtr(rhs).swap(*this);
}
void swap(RCPtr& rhs) noexcept
{
std::swap(px, rhs.px);
}
T* get() const noexcept
{
return px;
}
T& operator*() const noexcept
{
return *px;
}
T* operator->() const noexcept
{
return px;
}
explicit operator bool() const noexcept
{
return px != nullptr;
}
bool operator==(const RCPtr& rhs) const
{
return px == rhs.px;
}
bool operator!=(const RCPtr& rhs) const
{
return px != rhs.px;
}
template <typename U>
RCPtr<U> static_pointer_cast() const noexcept
{
return RCPtr<U>(static_cast<U*>(px));
}
template <typename U>
RCPtr<U> dynamic_pointer_cast() const noexcept
{
return RCPtr<U>(dynamic_cast<U*>(px));
}
private:
T* px;
};
// Reference count base class for objects tracked by RCPtr.
// Disallows copying and assignment.
template <typename RCImpl> // RCImpl = thread_safe_refcount or thread_unsafe_refcount
class RC
{
public:
typedef RCPtr<RC> Ptr;
RC() noexcept {}
virtual ~RC() {}
olong use_count() const noexcept
{
return refcount_.use_count();
}
static constexpr bool is_thread_safe()
{
return RCImpl::is_thread_safe();
}
private:
RC(const RC&) = delete;
RC& operator=(const RC&) = delete;
template <typename R> friend void intrusive_ptr_add_ref(R* p) noexcept;
template <typename R> friend void intrusive_ptr_release(R* p) noexcept;
RCImpl refcount_;
};
class Monster : public RC<thread_unsafe_refcount> {
std::string name;
int blood;
public:
typedef RCPtr<Monster> Ptr;
Monster(std::string n, int b=100) : name(n), blood(b) {}
void fight(int n) {blood-=n;}
};
int main(int argc, char* argv[]) {
Monster::Ptr m_p(new Monster("vampire"));
std::cout << m_p->use_count() << std::endl;
Monster::Ptr m_p2 = m_p;
//RCPtr<Monster> m1_p(&m1);
return 0;
}