Overture  Version 25
kk_ptr.hh
Go to the documentation of this file.
1 #ifndef KK_PTR
2 #define KK_PTR
3 
4 #include <iostream>
5 #include <typeinfo>
6 
7 #ifdef KK_PTR_DEBUG
8 
9 using std::cout;
10 using std::endl;
11 
12 #define KK_PTR_OUT(x) cout<<x;
13 
14 #ifndef KK_DEBUG
15 #define KK_DEBUG
16 #endif
17 
18 #else
19 
20 #define KK_PTR_OUT(x)
21 
22 #endif
23 
24 #include "kk_defines.hh"
25 
26 //#define KK_USE_VPTR
27 
28 namespace KK {
29 
31  long int acquire_gid();
32 
34  void release_gid(long int gid);
35 
37  class sptr_Err : public KK::Err {};
38 
39 #ifdef KK_USE_VPTR
40 
41  class vptr
42  {
43  public:
44  virtual ~vptr(){};
45 
46  virtual operator bool() const=0;
47  virtual long int GID() const=0;
48 
49  };
50 #endif
51 
53 
60  template<typename T>
61  class sptr
62 #ifdef KK_USE_VPTR
63 : public vptr
64 #endif
65  {
66  template<typename TO, typename FROM> friend sptr<TO> sptr_cast( sptr<FROM> &p );
67  template<typename TO, typename FROM> friend sptr<TO> sptr_static_cast( sptr<FROM> &p );
68  template<typename TO, typename FROM> friend sptr<TO> sptr_dynamic_cast( sptr<FROM> &p );
69  public:
70 
72  inline sptr(T*d_=0) : data(d_), count(0), gid(-1)
73  {
74  if (data)
75  {
76  gid=acquire_gid();
77  increment();
78  }
79  KK_PTR_OUT("built sptr for address "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
80  }
81 
83  inline sptr( const sptr<T> &p ) : data(p.data), count(p.count), gid(p.gid)
84  {
85  if ( data ) increment();
86  KK_PTR_OUT("built sptr for address "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
87  }
88 
90  inline
92  {
93  KK_PTR_OUT("del sptr for address "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
94  if ( data )
95  if ( decrement()==0 )
96  destroy();
97  else if ( (*count)<0 )
98  throw sptr_Err();
99  }
100 
102  inline sptr<T> & operator=( const sptr<T> & p )
103  {
104  if ( *this==p ) return *this;
105 
106  if ( data && decrement()==0 )
107  destroy();
108 
109  data = p.data;
110  count = p.count;
111  gid = p.gid;
112 
113  if ( data ) increment();
114 
115  KK_PTR_OUT("opr= sptr for address "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
116  return *this;
117  }
118 
120 
123  inline bool operator==(const sptr<T> &p) const
124  {
125  KK::Assert<sptr_Err> ( (data==p.data && gid==p.gid) || (data!=p.data && gid!=p.gid),
126  "ERROR: sptr_Err: sptr::== called but data and global id do not match!" );
127 
128  KK_PTR_OUT("this : "<<data<<" "<<gid<<" ; p : "<<p.data<<" "<<p.gid<<endl);
129  return (data==p.data && gid==p.gid);
130  }
131 
133 
136  inline bool operator!=(const sptr<T> &p) const
137  { return !(*this==p); }
138 
140  inline T* operator->()
141  {
142  KK::Assert<sptr_Err> ( data, "ERROR: sptr_Err: sptr-> called for null pointer!" );
143  return data;
144  }
145 
147  inline const T* operator->() const
148  {
149  KK::Assert<sptr_Err> ( data, "ERROR: sptr_Err: sptr-> called for null pointer!" );
150  return data;
151  }
152 
154  inline T& operator*()
155  {
156  KK::Assert<sptr_Err> ( data, "ERROR: sptr_Err: *sptr called for null pointer!" );
157  return *data;
158  }
159 
161  inline const T& operator*() const
162  {
163  KK::Assert<sptr_Err> ( data, "ERROR: sptr_Err: *sptr called for null pointer!" );
164  return *data;
165  }
166 
168  inline const T* raw() const
169  { return data; }
170 
172  inline operator bool() const
173  {
174  KK::Assert<sptr_Err>( (data==0&&gid==-1)||(data!=0 && gid>-1) );
175  return (data!=0 && gid>-1);
176  }
177 
179  inline long int GID() const { return gid; }
180 
182  inline int nRefs() const { return count ? *count : 0; }
183 
184  protected:
185 
187  sptr( T* rp, int * start_count, long int gid_) : data(rp), count(start_count), gid(gid_)
188  {
189  KK::Assert(start_count>0, "ERROR : protected sptr constructor : invalid initial count");
190 
191  if ( data ) increment();
192  }
193 
195  inline int increment()
196  {
197  // data has to be here for the increment to be valid (a null sptr should never get incremented)
198  KK::Assert<sptr_Err>( data, "ERROR: sptr_Err: sptr::increment called with no data!" );
199 
200  if ( !count )
201  {
202  count = new int;
203  (*count) = 0;
204  }
205 
206  KK_PTR_OUT("count is at address "<<count<<endl);
207  KK_PTR_OUT("incrementing "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
208 
209  return ++(*count);
210  }
211 
213  inline int decrement()
214  {
215  // data has to be here for the increment to be valid (a null sptr should never get decremented)
216  KK::Assert<sptr_Err>( data, "ERROR: sptr_Err: sptr::decrement called with no data!" );
217  // check to make sure the reference count makes at least a little sense (>0)
218  KK::Assert<sptr_Err>( count && (*count)>0,
219  "ERROR: sptr_Err: sptr::decrement called with invalid reference count!" );
220  KK_PTR_OUT("decrementing "<<data<<", gid "<<gid<<", count "<<(count ? (*count) : -1)<<endl);
221 
222  return --(*count);
223  }
224 
225  inline void destroy()
226  {
227  KK::Assert<sptr_Err>( (*count)==0, "ERROR: sptr_Err: sptr::destroy called with nonzero count!" );
228  delete data;
229  delete count;
230  data = 0;
231  count = 0;
232  release_gid(gid);
233  }
234 
235  private:
236  T *data;
237  int *count;
238  long int gid;
239  };
240 
242  template<typename TO, typename FROM>
243  inline
245  {
246  TO * to = static_cast<TO*>((FROM*)p.raw());
247 
248  if ( to )
249  return sptr<TO>(to, p.count, p.gid);
250  else
251  return sptr<TO>(); // just return a null pointer
252  }
253 
254  template<typename TO, typename FROM>
255  inline
257  {
258  return sptr_cast<TO>(p);
259  }
260 
261  template<typename TO, typename FROM>
262  inline
264  {
265  TO * to = dynamic_cast<TO*>((FROM*)p.raw());
266 
267  if ( to )
268  return sptr<TO>(to, p.count, p.gid);
269  else
270  return sptr<TO>(); // just return a null pointer
271  }
272 
273 #ifdef KK_USE_VPTR
274  template<typename TO>
275  inline
276  sptr<TO> vptr_cast( vptr &p )
277  {
278  sptr<TO> *sp = dynamic_cast< sptr<TO>* >(&p);
279  if ( sp )
280  return *sp;
281  else
282  return sptr<TO>();
283  }
284 #endif
285 }
286 
287 #endif