bes Updated for version 3.20.13
RCObject.cc
1
2// 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
40using std::endl;
41using std::string;
42
43namespace 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
62RCObject::~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
71int RCObject::ref() const
72{
73 ++_count;
74 BESDEBUG("ncml:memory", "Ref count for " << printRCObject() << " is now: " << _count << endl);
75 return _count;
76}
77
78int 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
116string RCObject::toString() const
117{
118 return printRCObject();
119}
120
121string 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
152void 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
197void 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...