Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarRefPtr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarRefPtr.hpp')
-rw-r--r--source/core/StarRefPtr.hpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/source/core/StarRefPtr.hpp b/source/core/StarRefPtr.hpp
new file mode 100644
index 0000000..906d4ff
--- /dev/null
+++ b/source/core/StarRefPtr.hpp
@@ -0,0 +1,303 @@
+#ifndef STAR_REF_PTR_HPP
+#define STAR_REF_PTR_HPP
+
+#include "StarException.hpp"
+#include "StarHash.hpp"
+
+namespace Star {
+
+// Reference counted ptr for intrusive reference counted types. Calls
+// unqualified refPtrIncRef and refPtrDecRef functions to manage the reference
+// count.
+template <typename T>
+class RefPtr {
+public:
+ typedef T element_type;
+
+ RefPtr();
+ explicit RefPtr(T* p, bool addRef = true);
+
+ RefPtr(RefPtr const& r);
+ RefPtr(RefPtr&& r);
+
+ template <typename T2>
+ RefPtr(RefPtr<T2> const& r);
+ template <typename T2>
+ RefPtr(RefPtr<T2>&& r);
+
+ ~RefPtr();
+
+ RefPtr& operator=(RefPtr const& r);
+ RefPtr& operator=(RefPtr&& r);
+
+ template <typename T2>
+ RefPtr& operator=(RefPtr<T2> const& r);
+ template <typename T2>
+ RefPtr& operator=(RefPtr<T2>&& r);
+
+ void reset();
+
+ void reset(T* r, bool addRef = true);
+
+ T& operator*() const;
+ T* operator->() const;
+ T* get() const;
+
+ explicit operator bool() const;
+
+private:
+ template <typename T2>
+ friend class RefPtr;
+
+ T* m_ptr;
+};
+
+template <typename T, typename U>
+bool operator==(RefPtr<T> const& a, RefPtr<U> const& b);
+
+template <typename T, typename U>
+bool operator!=(RefPtr<T> const& a, RefPtr<U> const& b);
+
+template <typename T>
+bool operator==(RefPtr<T> const& a, T* b);
+
+template <typename T>
+bool operator!=(RefPtr<T> const& a, T* b);
+
+template <typename T>
+bool operator==(T* a, RefPtr<T> const& b);
+
+template <typename T>
+bool operator!=(T* a, RefPtr<T> const& b);
+
+template <typename T, typename U>
+bool operator<(RefPtr<T> const& a, RefPtr<U> const& b);
+
+template <typename Type1, typename Type2>
+bool is(RefPtr<Type2> const& p);
+
+template <typename Type1, typename Type2>
+bool is(RefPtr<Type2 const> const& p);
+
+template <typename Type1, typename Type2>
+RefPtr<Type1> as(RefPtr<Type2> const& p);
+
+template <typename Type1, typename Type2>
+RefPtr<Type1 const> as(RefPtr<Type2 const> const& p);
+
+template <typename T, typename... Args>
+RefPtr<T> make_ref(Args&&... args);
+
+template <typename T>
+struct hash<RefPtr<T>> {
+ size_t operator()(RefPtr<T> const& a) const;
+
+ hash<T*> hasher;
+};
+
+// Base class for RefPtr that is NOT thread safe. This can have a performance
+// benefit over shared_ptr in single threaded contexts.
+class RefCounter {
+public:
+ friend void refPtrIncRef(RefCounter* p);
+ friend void refPtrDecRef(RefCounter* p);
+
+protected:
+ RefCounter();
+ virtual ~RefCounter() = default;
+
+private:
+ size_t m_refCounter;
+};
+
+template <typename T>
+RefPtr<T>::RefPtr()
+ : m_ptr(nullptr) {}
+
+template <typename T>
+RefPtr<T>::RefPtr(T* p, bool addRef)
+ : m_ptr(nullptr) {
+ reset(p, addRef);
+}
+
+template <typename T>
+RefPtr<T>::RefPtr(RefPtr const& r)
+ : RefPtr(r.m_ptr) {}
+
+template <typename T>
+RefPtr<T>::RefPtr(RefPtr&& r) {
+ m_ptr = r.m_ptr;
+ r.m_ptr = nullptr;
+}
+
+template <typename T>
+template <typename T2>
+RefPtr<T>::RefPtr(RefPtr<T2> const& r)
+ : RefPtr(r.m_ptr) {}
+
+template <typename T>
+template <typename T2>
+RefPtr<T>::RefPtr(RefPtr<T2>&& r) {
+ m_ptr = r.m_ptr;
+ r.m_ptr = nullptr;
+}
+
+template <typename T>
+RefPtr<T>::~RefPtr() {
+ if (m_ptr)
+ refPtrDecRef(m_ptr);
+}
+
+template <typename T>
+RefPtr<T>& RefPtr<T>::operator=(RefPtr const& r) {
+ reset(r.m_ptr);
+ return *this;
+}
+
+template <typename T>
+RefPtr<T>& RefPtr<T>::operator=(RefPtr&& r) {
+ if (m_ptr)
+ refPtrDecRef(m_ptr);
+
+ m_ptr = r.m_ptr;
+ r.m_ptr = nullptr;
+ return *this;
+}
+
+template <typename T>
+template <typename T2>
+RefPtr<T>& RefPtr<T>::operator=(RefPtr<T2> const& r) {
+ reset(r.m_ptr);
+ return *this;
+}
+
+template <typename T>
+template <typename T2>
+RefPtr<T>& RefPtr<T>::operator=(RefPtr<T2>&& r) {
+ if (m_ptr)
+ refPtrDecRef(m_ptr);
+
+ m_ptr = r.m_ptr;
+ r.m_ptr = nullptr;
+ return *this;
+}
+
+template <typename T>
+void RefPtr<T>::reset() {
+ reset(nullptr);
+}
+
+template <typename T>
+void RefPtr<T>::reset(T* r, bool addRef) {
+ if (m_ptr == r)
+ return;
+
+ if (m_ptr)
+ refPtrDecRef(m_ptr);
+
+ m_ptr = r;
+
+ if (m_ptr && addRef)
+ refPtrIncRef(m_ptr);
+}
+
+template <typename T>
+T& RefPtr<T>::operator*() const {
+ return *m_ptr;
+}
+
+template <typename T>
+T* RefPtr<T>::operator->() const {
+ return m_ptr;
+}
+
+template <typename T>
+T* RefPtr<T>::get() const {
+ return m_ptr;
+}
+
+template <typename T>
+RefPtr<T>::operator bool() const {
+ return m_ptr != nullptr;
+}
+
+template <typename T, typename U>
+bool operator==(RefPtr<T> const& a, RefPtr<U> const& b) {
+ return a.get() == b.get();
+}
+
+template <typename T, typename U>
+bool operator!=(RefPtr<T> const& a, RefPtr<U> const& b) {
+ return a.get() != b.get();
+}
+
+template <typename T>
+bool operator==(RefPtr<T> const& a, T* b) {
+ return a.get() == b;
+}
+
+template <typename T>
+bool operator!=(RefPtr<T> const& a, T* b) {
+ return a.get() != b;
+}
+
+template <typename T>
+bool operator==(T* a, RefPtr<T> const& b) {
+ return a == b.get();
+}
+
+template <typename T>
+bool operator!=(T* a, RefPtr<T> const& b) {
+ return a != b.get();
+}
+
+template <typename T, typename U>
+bool operator<(RefPtr<T> const& a, RefPtr<U> const& b) {
+ return a.get() < b.get();
+}
+
+template <typename Type1, typename Type2>
+bool is(RefPtr<Type2> const& p) {
+ return (bool)dynamic_cast<Type1*>(p.get());
+}
+
+template <typename Type1, typename Type2>
+bool is(RefPtr<Type2 const> const& p) {
+ return (bool)dynamic_cast<Type1 const*>(p.get());
+}
+
+template <typename Type1, typename Type2>
+RefPtr<Type1> as(RefPtr<Type2> const& p) {
+ return RefPtr<Type1>(dynamic_cast<Type1*>(p.get()));
+}
+
+template <typename Type1, typename Type2>
+RefPtr<Type1 const> as(RefPtr<Type2 const> const& p) {
+ return RefPtr<Type1>(dynamic_cast<Type1 const*>(p.get()));
+}
+
+template <typename T, typename... Args>
+RefPtr<T> make_ref(Args&&... args) {
+ return RefPtr<T>(new T(forward<Args>(args)...));
+}
+
+template <typename T>
+size_t hash<RefPtr<T>>::operator()(RefPtr<T> const& a) const {
+ return hasher(a.get());
+}
+
+inline void refPtrIncRef(RefCounter* p) {
+ ++p->m_refCounter;
+}
+
+inline void refPtrDecRef(RefCounter* p) {
+ if (--p->m_refCounter == 0)
+ delete p;
+}
+
+inline RefCounter::RefCounter()
+ : m_refCounter(0) {}
+
+}
+
+#endif