bakery  2.6
sharedptr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2004 Murray Cumming
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #ifndef BAKERY_UTILITIES_SHAREDPTR_H
20 #define BAKERY_UTILITIES_SHAREDPTR_H
21 
22 #include <iostream> //Just for debugging.
23 
24 namespace Bakery
25 {
26 
30 template< typename T_obj >
31 class sharedptr
32 {
33 public:
34  typedef size_t size_type;
35 
37  sharedptr();
38 
40  explicit sharedptr(T_obj* pobj);
41 
43  sharedptr(const sharedptr& src);
44 
46  sharedptr& operator=(const sharedptr& src);
47 
48  virtual ~sharedptr();
49 
52  inline T_obj& operator*();
53 
56  inline const T_obj& operator*() const;
57 
65  inline T_obj* operator->() const;
66 
75  inline operator bool() const;
76 
78  inline T_obj* obj();
79 
81  inline const T_obj* obj() const;
82 
83 
84 protected:
85  inline void ref();
86  inline void unref();
87 
88  size_type* m_pRefCount; //Shared between instances, by copying.
89  T_obj* m_pobj; //The underlying instance.
90 };
91 
92 template< typename T_obj>
94 : m_pRefCount(0), m_pobj(0)
95 {
96 
97 }
98 
99 template< typename T_obj>
101 : m_pRefCount(0), m_pobj(pobj)
102 {
103  //Start refcounting:
104  ref();
105 }
106 
107 template< typename T_obj>
109 : m_pRefCount(src.m_pRefCount), m_pobj(src.m_pobj)
110 {
111  ref();
112 }
113 
114 template< typename T_obj>
116 {
117  //std::cout << "sharedptr& operator=(const sharedptr& src)" << std::endl;
118  if(&src != this)
119  {
120  //Unref any existing stuff.
121  //operator= can never run before a constructor, so these values will be initialized already.
122  if(m_pobj) //The if() might not be required.
123  {
124  unref(); //Could cause a deallocation.
125  }
126 
127  //Copy:
128  m_pobj = src.m_pobj;
129 
130  m_pRefCount = src.m_pRefCount;
131  ref();
132  }
133 
134  return *this;
135 }
136 
137 template< typename T_obj>
139 {
140  unref();
141 }
142 
143 /*
144 template< typename T_obj>
145 void sharedptr<T_obj>::clear_without_deallocating()
146 {
147  m_pobj = 0;
148 }
149 */
150 
151 template< typename T_obj>
152 inline
154 {
155  return m_pobj;
156 }
157 
158 template< typename T_obj>
159 inline
160 const T_obj* sharedptr<T_obj>::obj() const
161 {
162  return m_pobj;
163 }
164 
165 template< typename T_obj>
166 inline
168 {
169  return *m_pobj;
170 }
171 
172 template< typename T_obj>
173 inline
174 const T_obj& sharedptr<T_obj>::operator*() const
175 {
176  return *m_pobj;
177 }
178 
179 template< typename T_obj>
180 inline
182 {
183  return m_pobj;
184 }
185 
186 template <class T_obj>
187 inline
189 {
190  return (m_pobj != 0);
191 }
192 
193 
194 template <class T_obj>
195 inline
197 {
198  if(m_pobj) //Don't waste time on invalid instances. These would be very rare anyway, and intentionally created with (0,0) construction.
199  {
200  if(m_pRefCount == 0)
201  {
202  //std::cout << "sharedptr::ref(): first ref" << std::endl;
203  //First ref, so allocate the shared count:
204  m_pRefCount = new size_type();
205  *m_pRefCount = 1;
206  }
207  else
208  {
209  //std::cout << "sharedptr::ref(): starting at" << *m_pRefCount << std::endl;
210  (*m_pRefCount)++;
211  }
212  }
213 }
214 
215 template <class T_obj>
216 inline
218 {
219  if(m_pRefCount)
220  {
221  //std::cout << "sharedptr::unref(): starting at " << *m_pRefCount << std::endl;
222 
223  if( (*m_pRefCount) > 0 )
224  (*m_pRefCount)--;
225 
226  //Unalloc if this is the last user of the obj:
227  if(*m_pRefCount == 0)
228  {
229  if(m_pobj)
230  {
231  //try
232  //{
233  //std::cout << "sharedptr::unref(): deallocating " << *m_pRefCount << std::endl;
234  delete m_pobj;
235  m_pobj = 0;
236  //}
237  /*
238  catch(ex_base&)
239  {
240  //std::cout << "sharedptr::unref(): exception thrown during deallocation." << std::endl;
241  //Ignore it. Can't throw an expection up to the destructor.
242  }
243  */
244 
245  m_pobj = 0;
246  }
247 
248  //Clear ref count:
249  delete m_pRefCount;
250  m_pRefCount = 0;
251  }
252  }
253  else
254  {
255  //std::cout << "sharedptr::unref(): ref not setup." << std::endl;
256  }
257 
258 }
259 
260 
261 } //namespace
262 
263 #endif //BAKERY_UTILITIES_SHAREDPTR_H
264 
T_obj * obj()
Get the underlying instance:
Definition: sharedptr.h:153
T_obj & operator*()
Dereferencing.
Definition: sharedptr.h:167
sharedptr & operator=(const sharedptr &src)
Share ownership.
Definition: sharedptr.h:115
void ref()
Definition: sharedptr.h:196
size_type * m_pRefCount
Definition: sharedptr.h:88
virtual ~sharedptr()
Definition: sharedptr.h:138
T_obj * operator->() const
Dereferencing.
Definition: sharedptr.h:181
size_t size_type
Definition: sharedptr.h:34
T_obj * m_pobj
Definition: sharedptr.h:89
sharedptr()
Allocate a new instance.
Definition: sharedptr.h:93
A shared reference-counting smart-pointer.
Definition: sharedptr.h:31
void unref()
Definition: sharedptr.h:217