bes  Updated for version 3.20.6
RCObject.h
1 // This file is part of the "NcML Module" project, a BES module designed
3 // to allow NcML files to be used to be used as a wrapper to add
4 // AIS to existing datasets of any format.
5 //
6 // Copyright (c) 2009 OPeNDAP, Inc.
7 // Author: Michael Johnson <m.johnson@opendap.org>
8 //
9 // For more information, please also see the main website: http://opendap.org/
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26 //
27 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29 #ifndef __AGG_UTIL__REF_COUNTED_OBJECT_H__
30 #define __AGG_UTIL__REF_COUNTED_OBJECT_H__
31 
32 #include "RCObjectInterface.h" // interface super
33 
34 #include <list>
35 #include <set>
36 #include <stdexcept>
37 #include <string>
38 #include <vector>
39 
40 namespace agg_util {
41 class RCOBjectPool;
42 class RCObject;
43 
44 typedef std::set<RCObject*> RCObjectSet;
45 
57 class RCObjectPool {
58  friend class RCObject;
59 
60 public:
62  RCObjectPool();
63 
65  virtual ~RCObjectPool();
66 
70  bool contains(RCObject* pObj) const;
71 
76  void add(RCObject* pObj);
77 
80  void remove(RCObject* pObj)
81  {
82  release(pObj, false);
83  }
84 
91  void release(RCObject* pObj, bool shouldDelete = true);
92 
93 protected:
97  void deleteAllObjects();
98 
99 private:
100 
101  // A set of the live, monitored objects.
102  // Lookups are log(N) and entries unique, as required.
103  // All entries in this list will be delete'd in the dtor.
104  RCObjectSet _liveObjects;
105 };
106 // class RCObjectPool
107 
114 public:
116  {
117  }
118  virtual ~UseCountHitZeroCB()
119  {
120  }
121  virtual void executeUseCountHitZeroCB(RCObject* pAboutToDie) = 0;
122 };
123 
164 class RCObject: public virtual RCObjectInterface // abstract interface
165 {
166  friend class RCObjectPool;
167 
168  typedef std::list<UseCountHitZeroCB*> PreDeleteCBList;
169 
170 private:
171  RCObject& operator=(const RCObject& rhs); //disallow
172 
173 public:
174 
178  RCObject(RCObjectPool* pool = 0);
179 
183  RCObject(const RCObject& proto);
184 
185  virtual ~RCObject();
186 
189  virtual int ref() const;
190 
201  virtual int unref() const;
202 
204  virtual int getRefCount() const;
205 
212  virtual void removeFromPool() const;
213 
215  virtual std::string toString() const;
216 
217 public:
218  // to workaround template friend issues. Not designed for public consumption.
219 
222 
225 
226 private:
227  // interface
228 
230  std::string printRCObject() const;
231 
242  void executeAndClearPreDeleteCallbacks();
243 
244 private:
245  // data rep
246 
247  // The reference count... mutable since we want to ref count const objects as well,
248  // and the count doesn't affect the semantic constness of the subclasses.
249  mutable int _count;
250 
251  // If not null, the object is from the given pool and should be release()'d to the
252  // pool when count hits 0, not deleted. If null, it can be deleted.
253  RCObjectPool* _pool;
254 
255  // Callback list for when the use count hits 0 but before deallocate
256  PreDeleteCBList _preDeleteCallbacks;
257 
258 };
259 // class RCObject
260 
283 template<class T>
284 class RCPtr {
285 public:
286  RCPtr(T* pRef = 0) :
287  _obj(pRef)
288  {
289  init();
290  }
291 
292  RCPtr(const RCPtr& from) :
293  _obj(from._obj)
294  {
295  init();
296  }
297 
298  ~RCPtr()
299  {
300  if (_obj) {
301  _obj->unref();
302  _obj = 0;
303  }
304  }
305 
306  RCPtr&
307  operator=(const RCPtr& rhs)
308  {
309  if (rhs._obj != _obj) {
310  RCObject* oldObj = _obj;
311  _obj = rhs._obj;
312  init();
313  if (oldObj) {
314  oldObj->unref();
315  }
316  }
317  return *this;
318  }
319 
320  T&
321  operator*() const
322  {
323  // caller is on their own if they deref this as null,
324  // so should check with get() first.
325  return *_obj;
326  }
327 
328  T*
329  operator->() const
330  {
331  return _obj;
332  }
333 
334  T*
335  get() const
336  {
337  return _obj;
338  }
339 
352  T*
353  refAndGet() const
354  {
355  if (_obj) {
356  _obj->ref();
357  }
358  return _obj;
359  }
360 
361 private:
362  void init()
363  {
364  if (_obj) {
365  _obj->ref();
366  }
367  }
368 
369 private:
370  T* _obj;
371 };
372 // class RCPtr<T>
373 
375 class BadWeakPtr: public std::runtime_error {
376 public:
377  BadWeakPtr(const std::string& msg) :
378  std::runtime_error(msg)
379  {
380  }
381 
382  virtual ~BadWeakPtr() throw ()
383  {
384  }
385 };
386 // class BadWeakPtr
387 
411 template<class T>
412 class WeakRCPtr: public UseCountHitZeroCB // can we private inherit this to avoid outside callers?
413 {
414 
415 public:
416 
419  _pObj(0)
420  {
421  }
422 
423  explicit WeakRCPtr(RCPtr<T> src)
424  {
425  // Connect to the shared ptr by adding listener and storing raw.
426  _pObj = src.get();
427  addMeAsListener();
428  }
429 
430  ~WeakRCPtr()
431  {
432  clear();
433  }
434 
435  WeakRCPtr& operator=(const WeakRCPtr& r)
436  {
437  if (&r != this) {
438  clear();
439  _pObj = r._pObj;
440  addMeAsListener();
441  }
442  return *this;
443  }
444 
446  bool expired() const
447  {
448  return empty();
449  }
450 
452  bool empty() const
453  {
454  return (!_pObj);
455  }
456 
457  RCPtr<T> lock() const
458  {
459  // return a safe shared ptr to the wrapped resource
460  // which will up it's count properly
461  if (_pObj) {
462  return RCPtr<T>(_pObj);
463  }
464  else {
465  return RCPtr<T>(NULL);
466  }
467  }
468 
472  void clear()
473  {
474  // Remove the listener, clear the ptr so it's like default ctor.
475  removeMeAsListener();
476  _pObj = NULL;
477  }
478 
479 public:
480  // to avoid template friend issues, but not for public use!
481 
487  virtual void executeUseCountHitZeroCB(RCObject* pAboutToDie)
488  {
489  if (pAboutToDie != _pObj) {
490  throw BadWeakPtr("executeUseCountHitZeroCB() called with mismatched raw pointers!");
491  }
492  clear();
493  }
494 
496 private:
497 
498  void removeMeAsListener()
499  {
500  if (_pObj) {
501  _pObj->removePreDeleteCB(this);
502  }
503  }
504 
505  void addMeAsListener()
506  {
507  if (_pObj) {
508  _pObj->addPreDeleteCB(this);
509  }
510  }
511 
512 private:
513  // data rep
514 
515  // The underlying wrapped object, or NULL if uninit or expired.
516  // NOTE: MUST be a subclass of RCObject
517  T* _pObj;
518 
519 };
520 // class WeakRCPtr<T>
521 
522 }// namespace agg_util
523 
524 #endif /* __AGG_UTIL__REF_COUNTED_OBJECT_H__ */
agg_util::RCObjectPool::release
void release(RCObject *pObj, bool shouldDelete=true)
Definition: RCObject.cc:195
agg_util::RCObject::unref
virtual int unref() const
Definition: RCObject.cc:76
agg_util::RCObject::toString
virtual std::string toString() const
Definition: RCObject.cc:114
agg_util::RCObject::removeFromPool
virtual void removeFromPool() const
Definition: RCObject.cc:104
agg_util::RCObjectPool::add
void add(RCObject *pObj)
Definition: RCObject.cc:186
agg_util::WeakRCPtr
Definition: RCObject.h:412
agg_util
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
Definition: AggMemberDataset.cc:38
agg_util::WeakRCPtr::WeakRCPtr
WeakRCPtr()
Definition: RCObject.h:418
agg_util::RCObjectPool::contains
bool contains(RCObject *pObj) const
Definition: RCObject.cc:180
agg_util::RCObject::RCObject
RCObject(RCObjectPool *pool=0)
Definition: RCObject.cc:43
agg_util::RCObject
A base class for a simple reference counted object.
Definition: RCObject.h:164
agg_util::RCObjectPool
Definition: RCObject.h:57
agg_util::RCObjectPool::~RCObjectPool
virtual ~RCObjectPool()
Definition: RCObject.cc:175
agg_util::WeakRCPtr::clear
void clear()
Definition: RCObject.h:472
agg_util::WeakRCPtr::expired
bool expired() const
Definition: RCObject.h:446
agg_util::RCObjectInterface
Definition: RCObjectInterface.h:39
agg_util::RCObjectPool::RCObjectPool
RCObjectPool()
Definition: RCObject.cc:170
agg_util::RCObject::addPreDeleteCB
void addPreDeleteCB(UseCountHitZeroCB *pCB)
Definition: RCObject.cc:127
agg_util::WeakRCPtr::empty
bool empty() const
Definition: RCObject.h:452
agg_util::BadWeakPtr
Definition: RCObject.h:375
agg_util::RCObjectPool::deleteAllObjects
void deleteAllObjects()
Definition: RCObject.cc:218
agg_util::RCObject::ref
virtual int ref() const
Definition: RCObject.cc:69
agg_util::RCPtr
A reference to an RCObject which automatically ref() and deref() on creation and destruction.
Definition: RCObject.h:284
agg_util::WeakRCPtr::executeUseCountHitZeroCB
virtual void executeUseCountHitZeroCB(RCObject *pAboutToDie)
Definition: RCObject.h:487
agg_util::RCObjectPool::remove
void remove(RCObject *pObj)
Definition: RCObject.h:80
agg_util::RCObject::removePreDeleteCB
void removePreDeleteCB(UseCountHitZeroCB *pCB)
Definition: RCObject.cc:140
agg_util::RCPtr::refAndGet
T * refAndGet() const
Definition: RCObject.h:353
agg_util::RCObject::getRefCount
virtual int getRefCount() const
Definition: RCObject.cc:99
agg_util::UseCountHitZeroCB
Definition: RCObject.h:113