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