OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
RCObject.cc
Go to the documentation of this file.
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 #include "RCObject.h"
30 
31 #include "BESDebug.h"
32 #include "NCMLDebug.h"
33 #include <algorithm> // std::find
34 #include <sstream>
35 #include <vector>
36 
37 namespace agg_util
38 {
41  , _count(0)
42  , _pool(pool)
43  , _preDeleteCallbacks()
44  {
45  if (_pool)
46  {
47  _pool->add(this);
48  }
49  }
50 
53  , _count(0) // new objects have no count, forget what the proto has!
54  , _pool(proto._pool)
55  , _preDeleteCallbacks()
56  {
57  if (_pool)
58  {
59  _pool->add(this);
60  }
61  }
62 
64  {
65  // just to let us know its invalid
66  _count = -1;
67 #if 0 // No exceptions in destructors. jhrg
68  NCML_ASSERT_MSG(_preDeleteCallbacks.empty(),
69  "~RCObject() called with a non-empty listener list!");
70 #endif
71  }
72 
73  int
74  RCObject::ref() const
75  {
76  ++_count;
77  BESDEBUG("ncml:memory", "Ref count for " << printRCObject() << " is now: " << _count << endl);
78  return _count;
79  }
80 
81  int
82  RCObject::unref() const throw()
83  {
84  int tmp = --_count; // need tmp since might delete and need _count valid at end
85  if (tmp == 0)
86  {
87  // Semantic constness here as well..
88  const_cast<RCObject*>(this)->executeAndClearPreDeleteCallbacks();
89  if (_pool)
90  {
91  BESDEBUG("ncml:memory", "Releasing back to pool: Object ref count hit 0. " << printRCObject() <<
92  " with toString() == " << toString() << endl);
93  _pool->release(const_cast<RCObject*>(this));
94  }
95  else
96  {
97  BESDEBUG("ncml:memory", "Calling delete: Object ref count hit 0. " << printRCObject() <<
98  " with toString() == " << toString() << endl);
99  delete this;
100  }
101  }
102  else
103  {
104  BESDEBUG("ncml:memory", "unref() called and: " << printRCObject() << endl);
105  }
106  return tmp;
107  }
108 
109  int
111  {
112  return _count;
113  }
114 
115  void
117  {
118  if (_pool)
119  {
120  // remove will not delete it
121  // and will clear _pool
122  _pool->remove(const_cast<RCObject*>(this));
123  NCML_ASSERT(!_pool);
124  }
125  }
126 
127  string
129  {
130  return printRCObject();
131  }
132 
133  string
134  RCObject::printRCObject() const
135  {
136  std::ostringstream oss;
137  oss << "RCObject@(" <<
138  reinterpret_cast<const void*>(this) <<
139  ") _count=" << _count <<
140  " numberDeleteListeners=" << _preDeleteCallbacks.size();
141  return oss.str();
142  }
143 
144  void
146  {
147  if (pCB)
148  {
149  // unique add
150  if (std::find(
151  _preDeleteCallbacks.begin(),
152  _preDeleteCallbacks.end(),
153  pCB) == _preDeleteCallbacks.end())
154  {
155  BESDEBUG("ncml:memory", "Adding WeakRCPtr listener: " << printRCObject() <<
156  " is getting listener: " << reinterpret_cast<const void*>(pCB) << endl);
157  _preDeleteCallbacks.push_back(pCB);
158  BESDEBUG("ncml:memory", "After listener add, obj is: " << printRCObject() << endl);
159  }
160  }
161  }
162 
163  void
165  {
166  if (pCB)
167  {
168  BESDEBUG("ncml:memory", "Removing WeakRCPtr listener from: " << printRCObject() <<
169  " Removed listener: " << reinterpret_cast<const void*>(pCB) << endl);
170  _preDeleteCallbacks.remove(pCB);
171  BESDEBUG("ncml:mempory", "Object after remove listener is: " << printRCObject() << endl);
172  }
173  }
174 
175  void
176  RCObject::executeAndClearPreDeleteCallbacks()
177  {
178  // Since the callbacks might remove themselves
179  // from the PreDeleteCBList, we can't use an
180  // iterator. Use the queue interface instead
181  // and force the deletion of a node when it's used
182  // to be sure the loop exits.
183  while (! (_preDeleteCallbacks.empty()) )
184  {
185  UseCountHitZeroCB* pCB = _preDeleteCallbacks.front();
186  _preDeleteCallbacks.pop_front();
187  if (pCB)
188  {
189  pCB->executeUseCountHitZeroCB(this);
190  }
191  }
192  NCML_ASSERT(_preDeleteCallbacks.empty());
193  }
194 
195 
198 
200  : _liveObjects()
201  {
202  }
203 
205  {
207  }
208 
209  bool
211  {
212  RCObjectSet::const_iterator foundIt = _liveObjects.find(pObj);
213  return (foundIt != _liveObjects.end());
214  }
215 
216  void
218  {
219  if (contains(pObj))
220  {
221  throw string("Internal Pool Error: Object added twice!");
222  }
223  _liveObjects.insert(pObj);
224  pObj->_pool = this;
225  }
226 
227  void
228  RCObjectPool::release(RCObject* pObj, bool shouldDelete/*=true*/)
229  {
230  if (contains(pObj))
231  {
232  _liveObjects.erase(pObj);
233  pObj->_pool = 0;
234 
235  if (shouldDelete)
236  {
237  // Delete it for now... If we decide to subclass and implement a real pool,
238  // we'll want to push this onto a vector for reuse.
239  BESDEBUG("ncml:memory", "RCObjectPool::release(): Calling delete on released object=" <<
240  pObj->printRCObject() <<
241  endl);
242  delete pObj;
243  }
244  else
245  {
246  BESDEBUG("ncml:memory", "RCObjectPool::release(): Removing object, but not deleting it: "
247  << pObj->printRCObject()
248  << endl);
249  }
250  }
251  else
252  {
253  BESDEBUG("ncml:memory", "ERROR: RCObjectPool::release() called on object not in pool!! Ignoring!" << endl);
254  }
255  }
256 
257  void
259  {
260  BESDEBUG("ncml:memory", "RCObjectPool::deleteAllObjects() started...." << endl);
261  RCObjectSet::iterator endIt = _liveObjects.end();
262  RCObjectSet::iterator it = _liveObjects.begin();
263  for (; it != endIt; ++it)
264  {
265  RCObject* pObj = *it;
266  // Just in case, flush the predelete list to avoid dangling WeakRCPtr
267  if (pObj)
268  {
269  pObj->executeAndClearPreDeleteCallbacks();
270  BESDEBUG("ncml:memory", "Calling delete on RCObject=" << pObj->printRCObject() << endl);
271  delete pObj;
272  }
273  }
274  _liveObjects.clear();
275  BESDEBUG("ncml:memory", "RCObjectPool::deleteAllObjects() complete!" << endl);
276  }
277 
278 
279 } // namespace agg_util
virtual std::string toString() const
Just prints the count and address.
Definition: RCObject.cc:128
RCObjectPool()
Create an empty pool.
Definition: RCObject.cc:199
void addPreDeleteCB(UseCountHitZeroCB *pCB)
Add uniquely.
Definition: RCObject.cc:145
virtual ~RCObject()
Definition: RCObject.cc:63
#define NCML_ASSERT(cond)
Definition: NCMLDebug.h:80
virtual int unref() const
Decrease the reference count by one.
Definition: RCObject.cc:82
void deleteAllObjects()
Call delete on all objects remaining in _liveObjects and clear it out.
Definition: RCObject.cc:258
A monitoring "pool" class for created RCObject's which allows us to forcibly delete any RCOBject's re...
Definition: RCObject.h:58
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
#define NCML_ASSERT_MSG(cond, msg)
Definition: NCMLDebug.h:83
RCObject(RCObjectPool *pool=0)
If the pool is given, the object will be released back to the pool when its count hits 0...
Definition: RCObject.cc:39
void remove(RCObject *pObj)
Remove the object from the pool, but don't delete it.
Definition: RCObject.h:82
void removePreDeleteCB(UseCountHitZeroCB *pCB)
Remove it exists.
Definition: RCObject.cc:164
virtual int ref() const
Increase the reference count by one.
Definition: RCObject.cc:74
void release(RCObject *pObj, bool shouldDelete=true)
Tell the pool that the object's count is 0 and it can be released to be deleted or potentially reused...
Definition: RCObject.cc:228
A base class for a simple reference counted object.
Definition: RCObject.h:162
Interface for registering callbacks to the RCObject for when the usecount hits 0 but before the deall...
Definition: RCObject.h:114
bool contains(RCObject *pObj) const
Definition: RCObject.cc:210
virtual ~RCObjectPool()
Forcibly delete all remaining objects in pool, regardless of ref count.
Definition: RCObject.cc:204
virtual int getRefCount() const
Get the current reference count.
Definition: RCObject.cc:110
virtual void executeUseCountHitZeroCB(RCObject *pAboutToDie)=0
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
void add(RCObject *pObj)
Add the object to the pool uniquely.
Definition: RCObject.cc:217
Interface class for a reference counted object.
virtual void removeFromPool() const
If the object is in an auto-delete pool, remove it from the pool and force it to only delete when it'...
Definition: RCObject.cc:116