bes  Updated for version 3.20.5
RCObject.cc
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 
30 #include "RCObject.h"
31 
32 #include "BESDebug.h"
33 #include "NCMLDebug.h"
34 #include <algorithm> // std::find
35 #include <sstream>
36 #include <vector>
37 
38 namespace agg_util {
39 
41  RCObjectInterface(), _count(0), _pool(pool), _preDeleteCallbacks()
42 {
43  if (_pool) {
44  _pool->add(this);
45  }
46 }
47 
49  RCObjectInterface(), _count(0) // new objects have no count, forget what the proto has!
50  , _pool(proto._pool), _preDeleteCallbacks()
51 {
52  if (_pool) {
53  _pool->add(this);
54  }
55 }
56 
57 RCObject::~RCObject()
58 {
59  // just to let us know its invalid
60  _count = -1;
61 
62  NCML_ASSERT_MSG(_preDeleteCallbacks.empty(),
63  "~RCObject() called with a non-empty listener list!");
64 }
65 
66 int RCObject::ref() const
67 {
68  ++_count;
69  BESDEBUG("ncml:memory", "Ref count for " << printRCObject() << " is now: " << _count << endl);
70  return _count;
71 }
72 
73 int RCObject::unref() const
74 {
75  int tmp = --_count; // need tmp since might delete and need _count valid at end
76  if (tmp == 0) {
77  // Semantic constness here as well..
78  const_cast<RCObject*>(this)->executeAndClearPreDeleteCallbacks();
79  if (_pool) {
80  BESDEBUG("ncml:memory",
81  "Releasing back to pool: Object ref count hit 0. " << printRCObject() << " with toString() == " << toString() << endl);
82  _pool->release(const_cast<RCObject*>(this));
83  }
84  else {
85  BESDEBUG("ncml:memory",
86  "Calling delete: Object ref count hit 0. " << printRCObject() << " with toString() == " << toString() << endl);
87  delete this;
88  }
89  }
90  else {
91  BESDEBUG("ncml:memory", "unref() called and: " << printRCObject() << endl);
92  }
93  return tmp;
94 }
95 
97 {
98  return _count;
99 }
100 
102 {
103  if (_pool) {
104  // remove will not delete it
105  // and will clear _pool
106  _pool->remove(const_cast<RCObject*>(this));
107  NCML_ASSERT(!_pool);
108  }
109 }
110 
111 string RCObject::toString() const
112 {
113  return printRCObject();
114 }
115 
116 string RCObject::printRCObject() const
117 {
118  std::ostringstream oss;
119  oss << "RCObject@(" << reinterpret_cast<const void*>(this) << ") _count=" << _count << " numberDeleteListeners="
120  << _preDeleteCallbacks.size();
121  return oss.str();
122 }
123 
125 {
126  if (pCB) {
127  // unique add
128  if (std::find(_preDeleteCallbacks.begin(), _preDeleteCallbacks.end(), pCB) == _preDeleteCallbacks.end()) {
129  BESDEBUG("ncml:memory",
130  "Adding WeakRCPtr listener: " << printRCObject() << " is getting listener: " << reinterpret_cast<const void*>(pCB) << endl);
131  _preDeleteCallbacks.push_back(pCB);
132  BESDEBUG("ncml:memory", "After listener add, obj is: " << printRCObject() << endl);
133  }
134  }
135 }
136 
138 {
139  if (pCB) {
140  BESDEBUG("ncml:memory",
141  "Removing WeakRCPtr listener from: " << printRCObject() << " Removed listener: " << reinterpret_cast<const void*>(pCB) << endl);
142  _preDeleteCallbacks.remove(pCB);
143  BESDEBUG("ncml:mempory", "Object after remove listener is: " << printRCObject() << endl);
144  }
145 }
146 
147 void RCObject::executeAndClearPreDeleteCallbacks()
148 {
149  // Since the callbacks might remove themselves
150  // from the PreDeleteCBList, we can't use an
151  // iterator. Use the queue interface instead
152  // and force the deletion of a node when it's used
153  // to be sure the loop exits.
154  while (!(_preDeleteCallbacks.empty())) {
155  UseCountHitZeroCB* pCB = _preDeleteCallbacks.front();
156  _preDeleteCallbacks.pop_front();
157  if (pCB) {
158  pCB->executeUseCountHitZeroCB(this);
159  }
160  }
161  NCML_ASSERT(_preDeleteCallbacks.empty());
162 }
163 
166 
168  _liveObjects()
169 {
170 }
171 
173 {
175 }
176 
178 {
179  RCObjectSet::const_iterator foundIt = _liveObjects.find(pObj);
180  return (foundIt != _liveObjects.end());
181 }
182 
184 {
185  if (contains(pObj)) {
186  throw string("Internal Pool Error: Object added twice!");
187  }
188  _liveObjects.insert(pObj);
189  pObj->_pool = this;
190 }
191 
192 void RCObjectPool::release(RCObject* pObj, bool shouldDelete/*=true*/)
193 {
194  if (contains(pObj)) {
195  _liveObjects.erase(pObj);
196  pObj->_pool = 0;
197 
198  if (shouldDelete) {
199  // Delete it for now... If we decide to subclass and implement a real pool,
200  // we'll want to push this onto a vector for reuse.
201  BESDEBUG("ncml:memory",
202  "RCObjectPool::release(): Calling delete on released object=" << pObj->printRCObject() << endl);
203  delete pObj;
204  }
205  else {
206  BESDEBUG("ncml:memory",
207  "RCObjectPool::release(): Removing object, but not deleting it: " << pObj->printRCObject() << endl);
208  }
209  }
210  else {
211  BESDEBUG("ncml:memory", "ERROR: RCObjectPool::release() called on object not in pool!! Ignoring!" << endl);
212  }
213 }
214 
216 {
217  BESDEBUG("ncml:memory", "RCObjectPool::deleteAllObjects() started...." << endl);
218  RCObjectSet::iterator endIt = _liveObjects.end();
219  RCObjectSet::iterator it = _liveObjects.begin();
220  for (; it != endIt; ++it) {
221  RCObject* pObj = *it;
222  // Just in case, flush the predelete list to avoid dangling WeakRCPtr
223  if (pObj) {
224  pObj->executeAndClearPreDeleteCallbacks();
225  BESDEBUG("ncml:memory", "Calling delete on RCObject=" << pObj->printRCObject() << endl);
226  delete pObj;
227  }
228  }
229  _liveObjects.clear();
230  BESDEBUG("ncml:memory", "RCObjectPool::deleteAllObjects() complete!" << endl);
231 }
232 
233 } // namespace agg_util
agg_util::RCObjectPool::release
void release(RCObject *pObj, bool shouldDelete=true)
Definition: RCObject.cc:192
agg_util::RCObject::unref
virtual int unref() const
Definition: RCObject.cc:73
agg_util::RCObject::toString
virtual std::string toString() const
Definition: RCObject.cc:111
agg_util::RCObject::removeFromPool
virtual void removeFromPool() const
Definition: RCObject.cc:101
agg_util::RCObjectPool::add
void add(RCObject *pObj)
Definition: RCObject.cc:183
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::RCObjectPool::contains
bool contains(RCObject *pObj) const
Definition: RCObject.cc:177
agg_util::RCObject::RCObject
RCObject(RCObjectPool *pool=0)
Definition: RCObject.cc:40
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:172
agg_util::RCObjectInterface
Definition: RCObjectInterface.h:39
agg_util::RCObjectPool::RCObjectPool
RCObjectPool()
Definition: RCObject.cc:167
agg_util::RCObject::addPreDeleteCB
void addPreDeleteCB(UseCountHitZeroCB *pCB)
Definition: RCObject.cc:124
agg_util::RCObjectPool::deleteAllObjects
void deleteAllObjects()
Definition: RCObject.cc:215
agg_util::RCObject::ref
virtual int ref() const
Definition: RCObject.cc:66
agg_util::RCObjectPool::remove
void remove(RCObject *pObj)
Definition: RCObject.h:80
agg_util::RCObject::removePreDeleteCB
void removePreDeleteCB(UseCountHitZeroCB *pCB)
Definition: RCObject.cc:137
agg_util::RCObject::getRefCount
virtual int getRefCount() const
Definition: RCObject.cc:96
agg_util::UseCountHitZeroCB
Definition: RCObject.h:113