cgv
Loading...
Searching...
No Matches
ref_ptr.h
1#pragma once
2
3#include "ref_counted.h"
4
5#include <cgv/defines/assert.h>
6#include <cgv/type/cond/is_base_of.h>
7#include <cgv/type/cond/has_virtual_destructor.h>
8#include <assert.h>
9
10#include "lib_begin.h"
11
12namespace cgv {
14 namespace data {
15
16// extern CGV_API bool validate_delete(const void* ptr);
17
18template <class T, bool is_ref_counted>
19class ref_ptr;
20
23{
24protected:
26 void inc_ref_count(const ref_counted* ptr) const
27 {
28 ptr->set_ref_count(ptr->get_ref_count()+1);
29 }
31 bool dec_ref_count(const ref_counted* ptr) const
32 {
33 int count = ptr->get_ref_count();
34 if (count > 0) {
35 ptr->set_ref_count(count-1);
36 return count == 1;
37 }
38 // ERROR: zero ref count decremented
39 assert(0);
40 return false;
41 }
42};
43
44template <typename T, bool is_ref_counted = false>
46{
47protected:
48 friend class ref_ptr_impl<const T, is_ref_counted>;
51 {
52 counter_type(T* p, int c) : ptr(p), count(c) {}
53 T* ptr;
54 int count;
55 };
59 void release()
60 {
61 if (counter) {
62 if (--counter->count == 0) {
63 delete counter->ptr;
64 counter->ptr = 0;
65 delete counter;
66 }
67 counter = 0;
68 }
69 }
71 T* ref () const { return counter ? counter->ptr : 0; }
73 explicit ref_ptr_impl(T* p = 0) : counter(0) {
74 if (p)
75 counter = new counter_type(p, 1);
76 }
79 {
80 if (counter)
81 ++counter->count;
82 }
84 template <typename S>
86 {
87 // ref_ptr conversion only valid if T is base of S
88 CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
89 // and T has a virtual destructor
91 // after validity checks, set pointer
92 counter = reinterpret_cast<counter_type*>(s.counter);
93 // and increment reference count
94 if (counter)
95 ++counter->count;
96 }
97public:
99 int get_count() const { return counter ? counter->count : 0; }
100};
101
102template <typename T>
103class ref_ptr_impl<T,true> : public ref_ptr_tag
104{
105 T* ptr;
106protected:
108 void release() {
109 if (ptr) {
110 if (dec_ref_count(ptr)) {
111// if (validate_delete(ptr))
112 delete ptr;
113 }
114 ptr = 0;
115 }
116 }
118 T* ref () const {
119 return ptr;
120 }
122 explicit ref_ptr_impl(T* p) : ptr(p) {
123 if (ptr)
124 inc_ref_count(ptr);
125 }
128 {
129 if (ptr)
130 inc_ref_count(ptr);
131 }
133 template <typename S>
135 {
136 // ref_ptr conversion only valid if T is base of S
137 CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
138 // and T has a virtual destructor
140 // after validity checks, set pointer with a very bad hack!!
141 ptr = static_cast<const ref_ptr<S,true>&>(s).operator->();
142 // and increment reference count
143 if (ptr)
144 inc_ref_count(ptr);
145 }
146public:
147 // void kill() { ptr = 0; }
149 int get_count() const {
150 return ptr ? ptr->get_ref_count() : 0;
151 }
152};
153
158template <class T, bool is_ref_counted = type::cond::is_base_of<ref_counted,T>::value>
159class ref_ptr : public ref_ptr_impl<T,is_ref_counted>
160{
161public:
166public:
168 ref_ptr(T* p = 0) : base_type(p) {}
170 ref_ptr(const this_type& r) : base_type(r) {}
173 this->release();
174 }
176 template <typename S>
179 template <typename S>
181 // ref_ptr conversion only valid if T is base of S
182 CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
183 // and S has a virtual destructor
185 // after validity checks, return converted pointer
187 *reinterpret_cast<const ref_ptr<S,is_ref_counted>*>(this)
188 );
189 }
192 if (this == &r)
193 return *this;
194 this->release();
195 new (this) this_type(r);
196 return *this;
197 }
199 template <typename S>
201 if (this == (const this_type*)&r)
202 return *this;
203 return *this = this_type(r);
204 }
206 T& operator*() const {
207 return *this->ref();
208 }
210 T* operator->() const {
211 return this->ref();
212 }
214 bool operator == (const this_type& r) const {
215 return this->ref() == r.ref();
216 }
218 bool operator < (const this_type& r) const {
219 return this->ref() < r.ref();
220 }
222 bool operator != (const this_type& r) const {
223 return this->ref() != r.ref();
224 }
226 bool unique() const {
227 return this->get_count() <= 1;
228 }
230 bool empty() const {
231 return this->get_count() == 0;
232 }
234 operator bool () const {
235 return !empty();
236 }
238 void clear() {
239 this->release();
240 }
241};
242
243 }
244}
245
246#include <cgv/config/lib_end.h>
if you derive your class from this class, a ref_ptr will do reference counting in the inhereted ref_c...
Definition ref_counted.h:11
int get_ref_count() const
read access to current count
Definition ref_counted.h:23
void set_ref_count(int c) const
write access is also const to allow ref counted pointers to const instances
Definition ref_counted.h:20
ref_ptr_impl(T *p)
construct from pointer and increment reference count
Definition ref_ptr.h:122
T * ref() const
return the pointer itself
Definition ref_ptr.h:118
ref_ptr_impl(const ref_ptr_impl< T, true > &r)
copy construct from same pointer type and increment count
Definition ref_ptr.h:127
int get_count() const
return the reference count
Definition ref_ptr.h:149
void release()
if the pointer had been initialized before, decrement reference count and release pointer,...
Definition ref_ptr.h:108
ref_ptr_impl(const ref_ptr_impl< S, true > &s)
copy construct from pointer of derived type with virtual destructor
Definition ref_ptr.h:134
void release()
decrement the count, delete if it is 0
Definition ref_ptr.h:59
int get_count() const
return current count
Definition ref_ptr.h:99
ref_ptr_impl(T *p=0)
construct reference counted pointer
Definition ref_ptr.h:73
counter_type * counter
store pointer to counter struct
Definition ref_ptr.h:57
T * ref() const
return the pointer itself
Definition ref_ptr.h:71
ref_ptr_impl(const ref_ptr_impl< T, false > &r)
copy construct from same pointer type and increment count
Definition ref_ptr.h:78
ref_ptr_impl(const ref_ptr_impl< S, false > &s)
copy construct from pointer of derived type with virtual destructor
Definition ref_ptr.h:85
struct used to make ref pointers to ref_counted friends of ref_counted
Definition ref_ptr.h:23
bool dec_ref_count(const ref_counted *ptr) const
decrement the count of a ref counted object and return whether to delete the object
Definition ref_ptr.h:31
void inc_ref_count(const ref_counted *ptr) const
increment the count of a ref counted object
Definition ref_ptr.h:26
reference counted pointer, which can work together with types that are derived from ref_counted,...
Definition ref_ptr.h:160
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
ref_ptr_impl< T, is_ref_counted > base_type
type of base class that implements the reference count specific methods
Definition ref_ptr.h:165
ref_ptr(const ref_ptr< S, is_ref_counted > &s)
allow to copy ref_ptr to a ref_ptr<T> if T is a base class of S and if T has a virtual destructor
Definition ref_ptr.h:177
T * operator->() const
access to element pointer
Definition ref_ptr.h:210
ref_ptr(const this_type &r)
copy constructor for reference pointers of the same type
Definition ref_ptr.h:170
bool unique() const
check if this is the only reference
Definition ref_ptr.h:226
void clear()
set to null pointer
Definition ref_ptr.h:238
ref_ptr(T *p=0)
construction from pointer or empty if pointer is not given
Definition ref_ptr.h:168
this_type & operator=(const this_type &r)
assignment to pointer of same type
Definition ref_ptr.h:191
~ref_ptr()
destruct reference counted pointer
Definition ref_ptr.h:172
bool operator!=(const this_type &r) const
compare by pointer
Definition ref_ptr.h:222
T & operator*() const
access to element
Definition ref_ptr.h:206
bool operator<(const this_type &r) const
compare by pointer
Definition ref_ptr.h:218
ref_ptr< S, is_ref_counted > down_cast() const
use static cast to convert from T to S if T is a base class of S and has a virtual destructor
Definition ref_ptr.h:180
ref_ptr< T, is_ref_counted > this_type
type of the reference counted pointer
Definition ref_ptr.h:163
bool operator==(const this_type &r) const
compare by pointer
Definition ref_ptr.h:214
the cgv namespace
Definition print.h:11
struct to store the pointer with a count
Definition ref_ptr.h:51
template condition returning, whether the passed type has a virtual destructor
template condition returning, whether the first argument is a base class of the second argument
Definition is_base_of.h:13