kDB: Knowledge DataBase
Loading...
Searching...
No Matches
SharedRef.h
1#include <atomic>
2
3namespace knowCore
4{
5 namespace details
6 {
8 {
9 template<typename _T_>
10 static bool canDelete(_T_*)
11 {
12 return true;
13 }
14 };
15 } // namespace details
21 template<typename _T_, typename _TDeleteCheck_ = details::SharedRefDefaultCheck>
23 {
24 template<typename _TOther_, typename _TDeleteCheckOther_>
25 friend class SharedRef;
26 public:
27 typedef _T_ ElementType;
28 public:
29 SharedRef() : m_data(nullptr) {}
34 SharedRef(_T_* _t, bool _own) : m_data(new Data)
35 {
36 m_data->t = _t;
37 ++m_data->count;
38 m_data->own = _own;
39 }
40 SharedRef(const SharedRef<_T_, _TDeleteCheck_>& _rhs) : m_data(nullptr) { ref(_rhs); }
41 SharedRef& operator=(const SharedRef<_T_, _TDeleteCheck_>& _rhs)
42 {
43 if(_rhs.m_data != m_data)
44 {
45 deref();
46 ref(_rhs);
47 }
48 return *this;
49 }
50 ~SharedRef() { deref(); }
51 public: // Casting operator
55 template<typename _TCast_>
57 {
58 using CastSharedRef = SharedRef<_TCast_, _TDeleteCheck_>;
59 CastSharedRef res;
60 if(m_data and dynamic_cast<_TCast_*>(m_data->t))
61 {
62 res.m_data = reinterpret_cast<typename CastSharedRef::Data*>(
63 m_data); // a bit ugly but all Data have the same layout
64 ++m_data->count;
65 }
66 return res;
67 }
71 template<typename _TCast_>
72 requires(std::is_base_of_v<_TCast_, _T_>)
74 {
75 using CastSharedRef = SharedRef<_TCast_, _TDeleteCheck_>;
76 CastSharedRef res;
77 if(m_data)
78 {
79 res.m_data = reinterpret_cast<typename CastSharedRef::Data*>(
80 m_data); // a bit ugly but all Data have the same layout
81 ++m_data->count;
82 }
83 return res;
84 }
85 public: // Comparison operator
86 bool operator==(const SharedRef<_T_>& _rhs) const
87 {
88 return m_data == _rhs.m_data or m_data->t == _rhs.m_data->t;
89 }
90 bool operator==(const _T_* _rhs) const
91 {
92 return (m_data and m_data->t == _rhs) or (not m_data and not _rhs);
93 }
94 operator bool() const { return m_data and m_data->t; }
95 public: // Access operator
96 bool isValid() const { return m_data and m_data->t; }
97 _T_* operator->() { return m_data->t; }
98 const _T_* operator->() const { return m_data->t; }
102 _T_* grab()
103 {
104 m_data->own = false;
105 return m_data->t;
106 }
107 _T_* data() { return m_data->t; }
108 const _T_* data() const { return m_data->t; }
109 private:
110 void deref()
111 {
112 if(m_data)
113 {
114 --m_data->count;
115 if(m_data->count == 0)
116 {
117 if(m_data->own and _TDeleteCheck_::canDelete(m_data->t))
118 {
119 delete m_data->t;
120 }
121 delete m_data;
122 }
123 m_data = nullptr;
124 }
125 }
126 void ref(const SharedRef<_T_, _TDeleteCheck_>& _rhs)
127 {
128 m_data = _rhs.m_data;
129 if(m_data)
130 {
131 ++m_data->count;
132 }
133 }
134 private:
135 struct Data
136 {
137 Data() : count(0) {}
138 Data(const Data& _rhs) = delete;
139 _T_* t = nullptr;
140 std::atomic<int> count;
141 bool own = false;
142 };
143 Data* m_data;
144 };
145} // namespace knowCore
Definition SharedRef.h:23
SharedRef< _TCast_, _TDeleteCheck_ > d_cast() const
Definition SharedRef.h:56
SharedRef(_T_ *_t, bool _own)
Definition SharedRef.h:34
_T_ * grab()
Definition SharedRef.h:102
SharedRef< _TCast_, _TDeleteCheck_ > s_cast() const
Definition SharedRef.h:73