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