Dibbler - a portable DHCPv6  1.0.2RC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SmartPtr.h
Go to the documentation of this file.
1 /*
2  * Dibbler - a portable DHCPv6
3  *
4  * authors: Tomasz Mrugalski <thomson@klub.com.pl>
5  * Marek Senderski <msend@o2.pl>
6  *
7  * Released under GNU GPL v2 licence
8  *
9  */
10 
11 #ifndef SmartPtr_H
12 #define SmartPtr_H
13 
14 #include <iostream>
15 
16 //Don't use this class alone, it's used only in casting
17 //one smartpointer to another smartpointer
18 //e.g.
19 //SPtr<a> a(new a()); SPtr<b> b(new(b)); a=b;
20 class Ptr {
21 public:
22  //constructor used in case of NULL SPtr
23  Ptr() {
24  ptr = NULL;
25  refcount = 1;
26  }
27  //Constructor used in case of non NULL SPtr
28  Ptr(void* object) {
29  ptr = object;
30  refcount = 1;
31  }
32 
33  int refcount; //refrence counter
34  void * ptr; //pointer to the real object
35 };
36 
37 template <class T>
38 class SPtr
39 {
40 
41 public:
45  SPtr();
46 
54  SPtr(T* something);
55 
56  SPtr(Ptr* voidptr) {
57  if(voidptr) {
58  ptr = voidptr;
59  ptr->refcount++;
60  } else {
61  ptr = new Ptr();
62  }
63  }
64 
65  Ptr* getPtr() {
66  return (ptr);
67  }
68 
69  SPtr(const SPtr& ref);
70 
71  SPtr& operator=(const SPtr& old);
72 
74  void reset() {
76  ptr = new Ptr();
77  }
78 
82  void reset(T* obj) {
84  ptr = new Ptr(obj);
85  }
86 
87  operator bool() const {
88  if (ptr && ptr->ptr) {
89  return true;
90  } else {
91  return false;
92  }
93  }
94 
95  int refCount();
96  ~SPtr();
97  T& operator*() const;
98  T* operator->() const;
99 
100  const T* get() const;
101 
105  template<class to>
107 
108  // Null pointer => return null pointer, too.
109  if (ptr->ptr == NULL) {
110  return SPtr<to>();
111  }
112 
113  // Try to dynamic cast the underlying pointer.
114  to* tmp = dynamic_cast<to*>( static_cast<T*>(ptr->ptr) );
115  if (tmp) {
116  // Cast was successful? Then return SmartPtr of the derived type
117  return SPtr<to>(ptr);
118  } else {
119  // Cast failed? Ok, incorrect type. Return null
120  return SPtr<to>();
121  }
122  }
123 
124 private:
125  void decrease_reference();
126 
127  Ptr * ptr;
128 };
129 
133 template<class to, class from>
135 
136  if (!from_ptr) {
137  return SPtr<to>();
138  }
139 
140  return from_ptr.template SPtr_cast<to>();
141 }
142 
143 template <class T>
145  if (!(--(ptr->refcount))) {
146  if (ptr->ptr) {
147  delete (T*)(ptr->ptr);
148  }
149  delete ptr;
150  }
151 }
152 
153 template <class T> SPtr<T>::SPtr() {
154  ptr = new Ptr();
155 }
156 
157 template <class T> int SPtr<T>::refCount() {
158  if (ptr) {
159  return ptr->refcount;
160  }
161  return 0;
162 }
163 
164 template <class T>
165 SPtr<T>::SPtr(T* something) {
166  ptr = new Ptr(something);
167 }
168 
169 template <class T>
170 SPtr<T>::SPtr(const SPtr& old) {
171 
172  // #include <typeinfo>
173  // std::cout << "### Copy constr " << typeid(T).name() << std::endl;
174  old.ptr->refcount++;
175  ptr = old.ptr;
176 
177  // This doesn't make sense. It just copies value to itself
178  //ptr->refcount = old.ptr->refcount;
179 }
180 
181 template <class T>
183  decrease_reference();
184 }
185 
193 template <class T>
194 T& SPtr<T>::operator*() const {
198  return *((T*)(ptr->ptr));
199 }
200 
207 template <class T>
209  if (!ptr) {
210  return 0;
211  }
212  return (T*)(ptr->ptr); //it can return NULL
213 }
214 
215 template <class T>
217  if (this==&old)
218  return *this;
219 
220  // If this pointer points to something...
221  if (this->ptr) {
222  if(!(--this->ptr->refcount))
223  {
224  if (this->ptr->ptr) {
225  // delete the object itself
226  delete (T*)(this->ptr->ptr);
227  }
228  // now delete its reference
229  delete this->ptr;
230  this->ptr = NULL;
231  }
232  }
233  this->ptr=old.ptr;
234  old.ptr->refcount++;
235  return *this;
236 }
237 #endif
238