reference.h
1 /*************************************************************************/
2 /* reference.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef REFERENCE_H
30 #define REFERENCE_H
31 
32 #include "object.h"
33 #include "safe_refcount.h"
34 #include "ref_ptr.h"
35 #include "object_type_db.h"
36 
40 class Reference : public Object{
41 
42  OBJ_TYPE( Reference, Object );
43 friend class RefBase;
44  SafeRefCount refcount;
45  SafeRefCount refcount_init;
46 protected:
47 
48  static void _bind_methods();
49 public:
50 
51 
52  _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get()<1; }
53  bool init_ref();
54  void reference();
55  bool unreference();
56  int reference_get_count() const;
57 
58  Reference();
59  ~Reference();
60 };
61 
62 #if 0
63 class RefBase {
64 protected:
65  void ref_inc(Reference *p_reference);
66  bool ref_dec(Reference *p_reference);
67  Reference *first_ref(Reference *p_reference);
68  Reference * get_reference_from_ref(const RefBase &p_base);
69  virtual Reference * get_reference() const=0;
70  char * get_refptr_data(const RefPtr &p_refptr) const;
71 public:
72 
73  virtual ~RefBase() {}
74 };
75 #endif
76 
77 template<class T>
78 class Ref {
79 
80  T *reference;
81 
82  void ref( const Ref& p_from ) {
83 
84  if (p_from.reference==reference)
85  return;
86 
87  unref();
88 
89  reference=p_from.reference;
90  if (reference)
91  reference->reference();
92  }
93 
94  void ref_pointer( T* p_ref ) {
95 
96  ERR_FAIL_COND(!p_ref);
97 
98  if (p_ref->init_ref())
99  reference=p_ref;
100  }
101 
102  //virtual Reference * get_reference() const { return reference; }
103 public:
104 
105 
106  _FORCE_INLINE_ bool operator<(const Ref<T>& p_r) const {
107 
108  return reference<p_r.reference;
109  }
110  _FORCE_INLINE_ bool operator==(const Ref<T>& p_r) const {
111 
112  return reference==p_r.reference;
113  }
114  _FORCE_INLINE_ bool operator!=(const Ref<T>& p_r) const {
115 
116  return reference!=p_r.reference;
117  }
118 
119  _FORCE_INLINE_ T* operator->() {
120 
121  return reference;
122  }
123 
124  _FORCE_INLINE_ T* operator*() {
125 
126  return reference;
127  }
128 
129  _FORCE_INLINE_ const T* operator->() const {
130 
131  return reference;
132  }
133 
134  _FORCE_INLINE_ const T* ptr() const {
135 
136  return reference;
137  }
138  _FORCE_INLINE_ T* ptr() {
139 
140  return reference;
141  }
142 
143  _FORCE_INLINE_ const T* operator*() const {
144 
145  return reference;
146  }
147 
148  RefPtr get_ref_ptr() const {
149 
150  RefPtr refptr;
151  Ref<Reference> * irr = reinterpret_cast<Ref<Reference>*>( refptr.get_data() );
152  *irr = *this;
153  return refptr;
154  };
155 
156 #if 0
157  // go to RefPtr
158  operator RefPtr() const {
159 
160  return get_ref_ptr();
161  }
162 #endif
163 
164 #if 1
165  operator Variant() const {
166 
167  return Variant( get_ref_ptr() );
168  }
169 #endif
170 
171  void operator=( const Ref& p_from ) {
172 
173  ref(p_from);
174  }
175 
176  template<class T_Other>
177  void operator=( const Ref<T_Other>& p_from ) {
178 
179  Reference *refb = const_cast<Reference*>(static_cast<const Reference*>(p_from.ptr()));
180  if (!refb) {
181  unref();
182  return;
183  }
184  Ref r;
185  r.reference=refb->cast_to<T>();
186  ref(r);
187  r.reference=NULL;
188  }
189 
190  void operator=( const RefPtr& p_refptr ) {
191 
192  Ref<Reference> * irr = reinterpret_cast<Ref<Reference>*>( p_refptr.get_data() );
193  Reference *refb = irr->ptr();
194  if (!refb) {
195  unref();
196  return;
197  }
198  Ref r;
199  r.reference=refb->cast_to<T>();
200  ref(r);
201  r.reference=NULL;
202  }
203 
204 
205  void operator=( const Variant& p_variant ) {
206 
207  RefPtr refptr=p_variant;
208  Ref<Reference> * irr = reinterpret_cast<Ref<Reference>*>( refptr.get_data() );
209  Reference *refb = irr->ptr();
210  if (!refb) {
211  unref();
212  return;
213  }
214  Ref r;
215  r.reference=refb->cast_to<T>();
216  ref(r);
217  r.reference=NULL;
218  }
219 
220  Ref( const Ref& p_from ) {
221 
222  reference=NULL;
223  ref(p_from);
224  }
225 
226  template<class T_Other>
227  Ref( const Ref<T_Other>& p_from ) {
228 
229  reference=NULL;
230  Reference *refb = const_cast<Reference*>(static_cast<const Reference*>(p_from.ptr()));
231  if (!refb) {
232  unref();
233  return;
234  }
235  Ref r;
236  r.reference=refb->cast_to<T>();
237  ref(r);
238  r.reference=NULL;
239  }
240 
241  Ref( T* p_reference ) {
242 
243  if (p_reference)
244  ref_pointer(p_reference);
245  else
246  reference=NULL;
247  }
248 
249  Ref( const Variant& p_variant) {
250 
251  RefPtr refptr=p_variant;
252  Ref<Reference> * irr = reinterpret_cast<Ref<Reference>*>( refptr.get_data() );
253  reference=NULL;
254  Reference *refb = irr->ptr();
255  if (!refb) {
256  unref();
257  return;
258  }
259  Ref r;
260  r.reference=refb->cast_to<T>();
261  ref(r);
262  r.reference=NULL;
263  }
264 
265 
266 
267  Ref( const RefPtr& p_refptr) {
268 
269  Ref<Reference> * irr = reinterpret_cast<Ref<Reference>*>( p_refptr.get_data() );
270  reference=NULL;
271  Reference *refb = irr->ptr();
272  if (!refb) {
273  unref();
274  return;
275  }
276  Ref r;
277  r.reference=refb->cast_to<T>();
278  ref(r);
279  r.reference=NULL;
280  }
281 
282  inline bool is_valid() const { return reference!=NULL; }
283  inline bool is_null() const { return reference==NULL; }
284 
285  void unref() {
286  //TODO this should be moved to mutexes, since this engine does not really
287  // do a lot of referencing on references and stuff
288  // mutexes will avoid more crashes?
289 
290  if (reference && reference->unreference()) {
291 
292  memdelete(reference);
293  }
294  reference=NULL;
295  }
296 
297  void instance() {
298  ref( memnew( T ));
299  }
300 
301  Ref() {
302 
303  reference=NULL;
304  }
305 
306  ~Ref() {
307 
308  unref();
309  }
310 
311 };
312 
313 typedef Ref<Reference> REF;
314 
315 
316 class WeakRef : public Reference {
317 
318  OBJ_TYPE(WeakRef,Reference);
319 
320  ObjectID ref;
321 protected:
322  static void _bind_methods();
323 
324 public:
325  Variant get_ref() const;
326  void set_obj(Object *p_object);
327  void set_ref(const REF& p_ref);
328 
329  WeakRef();
330 };
331 
332 
333 
334 #endif // REFERENCE_H
Definition: ref_ptr.h:40
Definition: reference.h:78
Definition: variant.h:74
Definition: safe_refcount.h:336
Definition: reference.h:40
Definition: reference.h:316
Definition: object.h:317