OpendTect  6.3
refcount.h
Go to the documentation of this file.
1 #pragma once
2 
3 /*+
4 ________________________________________________________________________
5 
6  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
7  Author: K. Tingdahl
8  Date: 13-11-2003
9  Contents: Basic functionality for reference counting
10 ________________________________________________________________________
11 
12 -*/
13 
14 #include "atomic.h"
15 #include "objectset.h"
16 #include "thread.h"
17 
18 template <class T> class WeakPtr;
19 template <class T> class RefMan;
20 template <class T> class ConstRefMan;
21 
22 
23 
108 namespace RefCount
110 {
111 class WeakPtrBase;
112 
116 mExpClass(Basic) Counter
117 {
118 public:
119  void ref();
120  bool tryRef();
124  bool unRef();
128  void unRefDontInvalidate();
130 
131  od_int32 count() const { return count_.load(); }
132  bool refIfReffed();
134 
135  void clearAllObservers();
136  void addObserver(WeakPtrBase* obj);
137  void removeObserver(WeakPtrBase* obj);
138 
139  Counter();
140  Counter(const Counter& a);
141 
142  static od_int32 cInvalidRefCount();
143  static od_int32 cStartRefCount();
144 
145 private:
146  ObjectSet<WeakPtrBase> observers_;
147  Threads::SpinLock observerslock_;
148 
150 };
151 
156 mExpClass(Basic) Referenced
157 {
158 public:
159 
160  void ref() const;
161  void unRef() const;
162  void unRefNoDelete() const;
163 
164 protected:
165 
166  Referenced() {}
167  Referenced(const Referenced&);
168  Referenced& operator =(const Referenced&);
169  virtual ~Referenced();
170 
171 private:
172  friend class WeakPtrBase;
173  virtual void refNotify() const {}
174  virtual void unRefNotify() const {}
175  virtual void unRefNoDeleteNotify() const {}
176  virtual void prepareForDelete() {}
179  mutable Counter refcount_;
180 
181 public:
182 
183  int nrRefs() const;
185  bool refIfReffed() const;
187  bool tryRef() const;
189 
190  void addObserver(WeakPtrBase* obs);
192  void removeObserver(WeakPtrBase* obs);
194  static bool isSane(const Referenced*);
195  /*Returns true if this really is a referenced
196  (i.e. has magicnumber set ) */
197 
198 private:
199 
200  const od_uint64 magicnumber_ = 0x123456789abcdef;
201 
202 };
203 
204 
205 template <class T>
206 inline void refIfObjIsReffed( const T* obj )
207 {
208  if ( obj )
209  {
210  mDynamicCastGet( const RefCount::Referenced*, reffed, obj );
211  if ( reffed )
212  reffed->ref();
213  }
214 }
215 
216 template <class T>
217 inline void unRefIfObjIsReffed( const T* obj )
218 {
219  if ( obj )
220  {
221  mDynamicCastGet( const RefCount::Referenced*, reffed, obj );
222  if ( reffed )
223  reffed->unRef();
224  }
225 }
226 
227 template <class T> inline void refIfObjIsReffed( const T& obj )
228 { refIfObjIsReffed( &obj ); }
229 template <class T> inline void unRefIfObjIsReffed( const T& obj )
230 { unRefIfObjIsReffed( &obj ); }
231 
232 
233 
234 mExpClass(Basic) WeakPtrBase
235 {
236 public:
237  operator bool() const;
238  bool operator!() const;
239  bool operator==( const WeakPtrBase& r ) const
240  { return ptr_==r.ptr_; }
241 protected:
242  WeakPtrBase();
243  void set(Referenced*);
244 
245  friend class Counter;
246 
247  void clearPtr();
248  mutable Threads::SpinLock lock_;
249  Referenced* ptr_;
250 };
251 
252 mExpClass(Basic) WeakPtrSetBase
253 {
254 public:
255  mExpClass(Basic) CleanupBlocker
256  {
257  public:
258  CleanupBlocker( WeakPtrSetBase& base )
259  : base_( base )
260  {
261  base_.blockCleanup();
262  }
263 
264  ~CleanupBlocker() { base_.unblockCleanup(); }
265  private:
266  WeakPtrSetBase& base_;
267 
268  };
269 
270 protected:
271  Threads::Atomic<int> blockcleanup_ = 0;
272 private:
273  friend class CleanupBlocker;
274  void blockCleanup();
275  void unblockCleanup();
276 };
277 
278 
279 }; //RefCount namespace end
280 
281 
285 template <class T>
286 mClass(Basic) WeakPtr : public RefCount::WeakPtrBase
287 {
288 public:
289  WeakPtr(RefCount::Referenced* p = 0) { set(p); }
290  WeakPtr(const WeakPtr<T>& p) : WeakPtr<T>( p.ptr_ ) {}
291  WeakPtr(RefMan<T>& p) : WeakPtr<T>(p.ptr()) {}
292  ~WeakPtr() { set( 0 ); }
293 
294  inline WeakPtr<T>& operator=(const WeakPtr<T>& p);
295  RefMan<T>& operator=(RefMan<T>& p)
296  { set(p.ptr()); return p; }
297  T* operator=(T* p)
298  { set(p); return p; }
299 
300  RefMan<T> get() const;
301 };
302 
303 
304 //A collection of weak pointers
305 
306 template <class T>
307 mClass(Basic) WeakPtrSet : public RefCount::WeakPtrSetBase
308 {
309 public:
310  bool operator+=(const WeakPtr<T>&);
311  //Returns if added (i.e. not duplicate)
312  bool operator+=(RefMan<T>&);
313  //Returns if added (i.e. not duplicate)
314  int size() const;
315  RefMan<T> operator[](int);
316  ConstRefMan<T> operator[](int) const;
317 
318  int indexOf(T*) const;
319 
320 
321 private:
322 
323  TypeSet<WeakPtr<T> > ptrs_;
324  mutable Threads::SpinLock lock_;
325 };
326 
327 
329 mGlobal(Basic) void unRefPtr( const RefCount::Referenced* ptr );
330 
332 mGlobal(Basic) void unRefNoDeletePtr( const RefCount::Referenced* ptr );
333 
335 mGlobal(Basic) const RefCount::Referenced*
336 refPtr( const RefCount::Referenced* ptr );
337 
339 template <class T> inline
340 void unRefAndZeroPtr( T*& ptr )
341 { unRefPtr( static_cast<RefCount::Referenced*>( ptr ) ); ptr = 0; }
342 
343 template <class T> inline
344 void unRefAndZeroPtr( const T*& ptr )
345 { unRefPtr( static_cast<const RefCount::Referenced*>( ptr ) ); ptr = 0; }
346 
347 mObjectSetApplyToAllFunc( deepUnRef, unRefPtr( os[idx] ), os.plainErase() )
348 mObjectSetApplyToAllFunc( deepUnRefNoDelete, unRefNoDeletePtr( os[idx] ),
349  os.plainErase() )
350 mObjectSetApplyToAllFunc( deepRef, refPtr( os[idx] ), )
351 
352 
353 
354 //Implementations and legacy stuff below
355 
356 
357 template <class T>
359 {
360  RefMan<T> ptr = p.get();
361  ptr.setNoDelete(true);
362  set(ptr.ptr());
363  return *this;
364 }
365 
366 
367 template <class T>
369 {
370  RefMan<T> res = 0;
371  if ( ptr_ && ptr_->tryRef() )
372  {
373  //reffed once through tryRef
374  res = (T*) ptr_;
375 
376  //unref the ref from tryRef
377  ptr_->unRef();
378  }
379 
380  return res;
381 }
382 
383 
384 template <class T> inline
385 bool WeakPtrSet<T>::operator+=(RefMan<T>& n)
386 {
387  T* ptr = n.ptr();
388  return WeakPtrSet<T>::operator+=( WeakPtr<T>( ptr ) );
389 }
390 
391 template <class T> inline
392 bool WeakPtrSet<T>::operator+=(const WeakPtr<T>& n)
393 {
394  lock_.lock();
395 
396  const bool cleanup = blockcleanup_.setIfValueIs( 0, -1 );
397  //Clean up old pointers
398  for ( int idx=ptrs_.size()-1; idx>=0; idx-- )
399  {
400  if ( cleanup && !ptrs_[idx] )
401  {
402  ptrs_.removeSingle( idx );
403  continue;
404  }
405 
406  if ( ptrs_[idx]==n )
407  {
408  if ( cleanup ) blockcleanup_ = 0;
409  lock_.unLock();
410  return false;
411  }
412  }
413 
414  if ( cleanup ) blockcleanup_ = 0;
415 
416  ptrs_ += n;
417  lock_.unLock();
418 
419  return true;
420 }
421 
422 
423 template <class T> inline
424 int WeakPtrSet<T>::size() const
425 {
426  lock_.lock();
427  const int res = ptrs_.size();
428  lock_.unLock();
429  return res;
430 }
431 
432 
433 template <class T> inline
434 RefMan<T> WeakPtrSet<T>::operator[]( int idx )
435 {
436  lock_.lock();
437  RefMan<T> res = ptrs_.validIdx(idx) ? ptrs_[idx].get() : RefMan<T>( 0 );
438  lock_.unLock();
439  return res;
440 }
441 
442 
443 
444 template <class T> inline
445 ConstRefMan<T> WeakPtrSet<T>::operator[]( int idx ) const
446 {
447  return const_cast<WeakPtrSet<T>*>( this )->operator[](idx);
448 }
#define mExpClass(module)
Definition: commondefs.h:157
bool operator==(const ArrayNDInfo &a1, const ArrayNDInfo &a2)
Definition: arrayndinfo.h:51
void setNoDelete(bool yn)
Definition: ptrman.h:489
#define mGlobal(module)
Definition: commondefs.h:160
ObjectSet< T >::size_type indexOf(const ObjectSet< T > &os, const S &val)
Locate object in set.
Definition: objectset.h:173
Set of pointers to objects.
Definition: commontypes.h:28
Set of (small) copyable elements.
Definition: commontypes.h:26
Is an alternative to Mutex. It is a lock which causes a thread trying to acquire it to simply wait in...
Definition: atomic.h:130
static void unRef(T *p)
Definition: ptrman.h:500
#define mDynamicCastGet(typ, out, in)
Definition: commondefs.h:123
#define od_uint64
Definition: plftypes.h:35
#define od_int32
Definition: plftypes.h:29
#define mObjectSetApplyToAllFunc(fn, op, extra)
Definition: objectset.h:112
Definition: atomic.h:27
Definition: ptrman.h:22
#define mClass(module)
Definition: commondefs.h:161
Definition: ptrman.h:227
const T * ptr() const
Definition: ptrman.h:95
Definition: ptrman.h:200

Generated at for the OpendTect seismic interpretation project. Copyright (C): dGB Beheer B. V. 2017