ReferenceTo.h
1 //-*-C++-*-
2 /***************************************************************************
3  *
4  * Copyright (C) 2004 - 2023 by Willem van Straten
5  * Licensed under the Academic Free License version 2.1
6  *
7  ***************************************************************************/
8 
9 // psrchive/Util/units/ReferenceTo.h
10 
11 #ifndef __ReferenceTo_h
12 #define __ReferenceTo_h
13 
14 // #define _DEBUG 1
15 #include "debug.h"
16 #include "ReferenceAble.h"
17 #include "Error.h"
18 
19 #include <typeinfo>
20 #include <string>
21 
22 namespace Reference {
23 
25  template<class Type, bool active = true> class To {
26 
27  public:
28 
30  bool operator ! () const;
31 
33  operator bool () const;
34 
36  To (Type* ptr = 0);
37 
39  To (const To&);
40 
42  ~To ();
43 
45  To& operator = (const To&);
46 
48  To& operator = (Type *);
49 
51  Type& operator * () const { return *get(); }
52 
54  Type* operator -> () const { return get(); }
55 
57  operator Type* () const { return get(); }
58 
60  Type* get () const;
61 
63  Type* release ();
64 
66  const Type* ptr () const;
67 
69  Type* ptr ();
70 
72  std::string name () const;
73 
74  private:
75 
77  void hook (const Able*);
78 
80  void unhook (bool auto_delete = true);
81 
83  Able::Handle* the_handle;
84 
85  };
86 }
87 
88 template<class Type, bool active>
89 void Reference::To<Type,active>::unhook (bool auto_delete)
90 {
91  DEBUG("Reference::To<"+name()+">::unhook handle=" << the_handle << " auto_delete=" << auto_delete);
92 
93  if (!the_handle)
94  return;
95 
96  Able::Handle* temp = the_handle;
97 
98  the_handle = 0;
99 
100  // thread-safe handle detachment
101  temp->decrement (active, auto_delete);
102 }
103 
104 template<class Type, bool active>
105 void Reference::To<Type,active>::hook (const Able* pointer)
106 {
107  DEBUG("Reference::To<"+name()+">::handle Able*="<< pointer);
108 
109  if (!pointer)
110  the_handle = 0;
111  else
112  the_handle = pointer->__reference (active);
113 }
114 
115 template<class Type, bool active>
117 {
118 #ifdef _DEBUG
119  return "T";
120 #else
121  return typeid(Type).name();
122 #endif
123 }
124 
125 template<class Type, bool active>
127 {
128  DEBUG("Reference::To<"+name()+">::To (Type*="<< (void*)ref_pointer <<")");
129 
130  the_handle = 0;
131  hook (ref_pointer);
132 }
133 
134 template<class Type, bool active>
136 {
137  DEBUG("Reference::To<"+name()+">::~To");
138 
139  unhook ();
140 }
141 
142 template<class Type, bool active>
144 {
145  DEBUG("Reference::To<"+name()+">::operator !");
146 
147  return !the_handle || the_handle->pointer == 0;
148 }
149 
150 template<class Type, bool active>
152 {
153  DEBUG("Reference::To<"+name()+">::operator bool");
154 
155  return the_handle && the_handle->pointer;
156 }
157 
158 // copy constructor
159 template<class Type, bool active>
160 Reference::To<Type,active>::To (const To& another_reference)
161 {
162  DEBUG("Reference::To<"+name()+">::To (To<Type>)");
163 
164  // thread-safe copy
165  the_handle = 0;
166  Able::Handle::copy (the_handle, another_reference.the_handle, active);
167 }
168 
169 
170 // operator = copy assignment operator
171 template<class Type, bool active>
174 {
175  DEBUG("Reference::To<"+name()+">::operator = (To<Type>)");
176 
177  if (the_handle == oref.the_handle)
178  return *this;
179 
180  unhook ();
181 
182  // thread-safe copy
183  Able::Handle::copy (the_handle, oref.the_handle, active);
184 
185  return *this;
186 }
187 
188 // operator = assignment operator
189 template<class Type, bool active>
192 {
193  DEBUG("Reference::To<"+name()+">::operator = (Type*=" << (void*)ref_pointer <<")");
194 
195  if (the_handle && the_handle->pointer == ref_pointer)
196  return *this;
197 
198  unhook ();
199 
200  hook (ref_pointer);
201 
202  return *this;
203 }
204 
205 template<class Type, bool active>
207 {
208  DEBUG("Reference::To<"+name()+">::get");
209 
210  if (!the_handle || the_handle->pointer == 0)
211  throw Error (InvalidPointer, "Reference::To<"+name()+">::get");
212 
213  return reinterpret_cast<Type*>( the_handle->pointer );
214 }
215 
216 
217 template<class Type, bool active>
219 {
220  DEBUG("Reference::To<"+name()+">::release");
221 
222  if (!the_handle || the_handle->pointer == 0)
223  throw Error (InvalidPointer, "Reference::To<"+name()+">::release");
224 
225  Type* copy = reinterpret_cast<Type*>( the_handle->pointer );
226 
227  unhook (false);
228 
229  return copy;
230 }
231 
233 template<class Type, bool active>
235 {
236  if (the_handle)
237  return reinterpret_cast<const Type*>( the_handle->pointer );
238  else
239  return 0;
240 }
241 
243 template<class Type, bool active>
245 {
246  if (the_handle && the_handle->pointer)
247  return reinterpret_cast<Type*>( the_handle->pointer );
248  else
249  return 0;
250 }
251 
252 template<class Type, bool active>
254 {
255  DEBUG("swap (Reference::To<Type>, ditto)");
256 
257  Type* ref1_ptr = ref1.release();
258  Type* ref2_ptr = ref2.release();
259 
260  ref1 = ref2_ptr;
261  ref2 = ref1_ptr;
262 }
263 
265 template<class Type1, bool active1, class Type2, bool active2>
266 bool operator == (const Reference::To<Type1,active1>& ref1,
267  const Reference::To<Type2,active2>& ref2)
268 {
269  DEBUG("operator == (Reference::To<Type>&, Reference::To<Type2>&)");
270 
271  return ref1.ptr() == ref2.ptr();
272 }
273 
275 template<class Type1, bool active1, class Type2, bool active2>
276 bool operator != (const Reference::To<Type1,active1>& ref1,
277  const Reference::To<Type2,active2>& ref2)
278 {
279  DEBUG("operator != (Reference::To<Type>&, Reference::To<Type2>&)");
280 
281  return ref1.ptr() != ref2.ptr();
282 }
283 
284 
286 template<class Type, bool active, class Type2>
287 bool operator == (const Reference::To<Type,active>& ref, const Type2* instance)
288 {
289  DEBUG("operator == (Reference::To<Type>&, Type*)");
290 
291  return ref.ptr() == instance;
292 }
293 
295 template<class Type, bool active, class Type2>
296 bool operator == (const Type2* instance, const Reference::To<Type,active>& ref)
297 {
298  DEBUG("operator == (T2*, Reference::To<T1>&)");
299 
300  return ref.ptr() == instance;
301 }
302 
303 template<typename C, typename P, bool A>
304 C* dynamic_kast (Reference::To<P,A>& p)
305 {
306  return dynamic_cast<C*> (p.ptr());
307 }
308 
309 template<typename P, bool A>
310 P* const_kast (Reference::To<const P,A>& p)
311 {
312  return const_cast<P*> (p.ptr());
313 }
314 
315 #endif // #ifndef __ReferenceTo_h
316 
bool operator!() const
Returns true if reference is null.
Definition: ReferenceTo.h:143
Contains two basic classes that simplify dynamic memory management.
Definition: HeapTracked.h:17
A convenient exception handling class.
Definition: Error.h:54
To(Type *ptr=0)
Default constructor.
Definition: ReferenceTo.h:126
Type * release()
Return the pointer and unhook without deleting the object.
Definition: ReferenceTo.h:218
Type * get() const
Return the pointer.
Definition: ReferenceTo.h:206
Template class manages Reference::Able objects.
Definition: Reference.h:74
std::string name() const
Return the name of the object, as returned by typeid.
Definition: ReferenceTo.h:116
~To()
Destructor.
Definition: ReferenceTo.h:135
Manages Reference::To references to the instance.
Definition: ReferenceAble.h:40
Definition: ReferenceAble.h:86
const Type * ptr() const
Return pointer without testing for validity.
Definition: ReferenceTo.h:234
Type * operator->() const
Member dereferencing operator.
Definition: ReferenceTo.h:64
To & operator=(const To &)
Assignment operator.
Definition: ReferenceTo.h:173
Type & operator*() const
Object dereferencing operator.
Definition: ReferenceTo.h:61

Generated using doxygen 1.8.17