1. #include <string>
    2. #include <thread>
    3. #include <iostream>
    4. #include <type_traits>
    5. #include <cxxabi.h>
    6. #include <memory>
    7. #define OPENVPN_RC_DEBUG
    8. #if defined(_MSC_VER) && defined(_M_X64)
    9. typedef long long olong;
    10. typedef unsigned long long oulong;
    11. #else
    12. typedef long olong;
    13. typedef unsigned long oulong;
    14. #endif
    15. inline std::string cxx_demangle(const char *mangled_name)
    16. {
    17. int status;
    18. std::unique_ptr<char[]> realname;
    19. realname.reset(abi::__cxa_demangle(mangled_name, 0, 0, &status));
    20. if (!status)
    21. return std::string(realname.get());
    22. else
    23. return "DEMANGLE_ERROR";
    24. }
    25. template <typename R>
    26. inline void intrusive_ptr_add_ref(R *p) noexcept
    27. {
    28. #ifdef OPENVPN_RC_DEBUG
    29. std::cout << "ADD REF " << cxx_demangle(typeid(p).name()) << std::endl;
    30. #endif
    31. ++p->refcount_;
    32. }
    33. template <typename R>
    34. inline void intrusive_ptr_release(R *p) noexcept
    35. {
    36. if (--p->refcount_ == 0)
    37. {
    38. #ifdef OPENVPN_RC_DEBUG
    39. std::cout << "DEL OBJ " << cxx_demangle(typeid(p).name()) << std::endl;
    40. #endif
    41. delete p;
    42. }
    43. else
    44. {
    45. #ifdef OPENVPN_RC_DEBUG
    46. std::cout << "REL REF " << cxx_demangle(typeid(p).name()) << std::endl;
    47. #endif
    48. }
    49. }
    50. class thread_unsafe_refcount
    51. {
    52. public:
    53. thread_unsafe_refcount() noexcept
    54. : rc(olong(0))
    55. {
    56. }
    57. void operator++() noexcept
    58. {
    59. ++rc;
    60. }
    61. olong operator--() noexcept
    62. {
    63. return --rc;
    64. }
    65. bool inc_if_nonzero() noexcept
    66. {
    67. if (rc)
    68. {
    69. ++rc;
    70. return true;
    71. }
    72. else
    73. return false;
    74. }
    75. olong use_count() const noexcept
    76. {
    77. return rc;
    78. }
    79. static constexpr bool is_thread_safe()
    80. {
    81. return false;
    82. }
    83. private:
    84. thread_unsafe_refcount(const thread_unsafe_refcount&) = delete;
    85. thread_unsafe_refcount& operator=(const thread_unsafe_refcount&) = delete;
    86. olong rc;
    87. };
    88. // The smart pointer class
    89. template <typename T>
    90. class RCPtr
    91. {
    92. public:
    93. typedef T element_type;
    94. RCPtr() noexcept
    95. : px(nullptr)
    96. {
    97. }
    98. RCPtr(T* p, const bool add_ref=true) noexcept
    99. : px(p)
    100. {
    101. if (px && add_ref)
    102. intrusive_ptr_add_ref(px);
    103. }
    104. RCPtr(const RCPtr& rhs) noexcept
    105. : px(rhs.px)
    106. {
    107. if (px)
    108. intrusive_ptr_add_ref(px);
    109. }
    110. RCPtr(RCPtr&& rhs) noexcept
    111. : px(rhs.px)
    112. {
    113. rhs.px = nullptr;
    114. }
    115. template <typename U>
    116. RCPtr(const RCPtr<U>& rhs) noexcept
    117. : px(rhs.get())
    118. {
    119. if (px)
    120. intrusive_ptr_add_ref(px);
    121. }
    122. ~RCPtr()
    123. {
    124. if (px)
    125. intrusive_ptr_release(px);
    126. }
    127. RCPtr& operator=(const RCPtr& rhs) noexcept
    128. {
    129. RCPtr(rhs).swap(*this);
    130. return *this;
    131. }
    132. RCPtr& operator=(RCPtr&& rhs) noexcept
    133. {
    134. RCPtr(std::move(rhs)).swap(*this);
    135. return *this;
    136. }
    137. void reset() noexcept
    138. {
    139. RCPtr().swap(*this);
    140. }
    141. void reset(T* rhs) noexcept
    142. {
    143. RCPtr(rhs).swap(*this);
    144. }
    145. void swap(RCPtr& rhs) noexcept
    146. {
    147. std::swap(px, rhs.px);
    148. }
    149. T* get() const noexcept
    150. {
    151. return px;
    152. }
    153. T& operator*() const noexcept
    154. {
    155. return *px;
    156. }
    157. T* operator->() const noexcept
    158. {
    159. return px;
    160. }
    161. explicit operator bool() const noexcept
    162. {
    163. return px != nullptr;
    164. }
    165. bool operator==(const RCPtr& rhs) const
    166. {
    167. return px == rhs.px;
    168. }
    169. bool operator!=(const RCPtr& rhs) const
    170. {
    171. return px != rhs.px;
    172. }
    173. template <typename U>
    174. RCPtr<U> static_pointer_cast() const noexcept
    175. {
    176. return RCPtr<U>(static_cast<U*>(px));
    177. }
    178. template <typename U>
    179. RCPtr<U> dynamic_pointer_cast() const noexcept
    180. {
    181. return RCPtr<U>(dynamic_cast<U*>(px));
    182. }
    183. private:
    184. T* px;
    185. };
    186. // Reference count base class for objects tracked by RCPtr.
    187. // Disallows copying and assignment.
    188. template <typename RCImpl> // RCImpl = thread_safe_refcount or thread_unsafe_refcount
    189. class RC
    190. {
    191. public:
    192. typedef RCPtr<RC> Ptr;
    193. RC() noexcept {}
    194. virtual ~RC() {}
    195. olong use_count() const noexcept
    196. {
    197. return refcount_.use_count();
    198. }
    199. static constexpr bool is_thread_safe()
    200. {
    201. return RCImpl::is_thread_safe();
    202. }
    203. private:
    204. RC(const RC&) = delete;
    205. RC& operator=(const RC&) = delete;
    206. template <typename R> friend void intrusive_ptr_add_ref(R* p) noexcept;
    207. template <typename R> friend void intrusive_ptr_release(R* p) noexcept;
    208. RCImpl refcount_;
    209. };
    210. class Monster : public RC<thread_unsafe_refcount> {
    211. std::string name;
    212. int blood;
    213. public:
    214. typedef RCPtr<Monster> Ptr;
    215. Monster(std::string n, int b=100) : name(n), blood(b) {}
    216. void fight(int n) {blood-=n;}
    217. };
    218. int main(int argc, char* argv[]) {
    219. Monster::Ptr m_p(new Monster("vampire"));
    220. std::cout << m_p->use_count() << std::endl;
    221. Monster::Ptr m_p2 = m_p;
    222. //RCPtr<Monster> m1_p(&m1);
    223. return 0;
    224. }