diff options
Diffstat (limited to 'src/base/ObjectCounter.cpp')
-rw-r--r-- | src/base/ObjectCounter.cpp | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/base/ObjectCounter.cpp b/src/base/ObjectCounter.cpp new file mode 100644 index 0000000..e8136b7 --- /dev/null +++ b/src/base/ObjectCounter.cpp @@ -0,0 +1,187 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "ObjectCounter.h" +#include "Exception.h" +#include "Logger.h" + +#include <boost/thread/mutex.hpp> + +#include <iostream> +#include <sstream> +#include <vector> +#include <algorithm> + +#ifdef WIN32 +#include <windows.h> +#include <Dbghelp.h> +#else +#include <cxxabi.h> +#endif + +#define DEBUG_ALLOC 1 + +namespace avg { + +using namespace std; + +ObjectCounter* ObjectCounter::s_pObjectCounter = 0; +bool ObjectCounter::s_bDeleted = false; +boost::mutex * pCounterMutex; + +void deleteObjectCounter() +{ + delete ObjectCounter::s_pObjectCounter; + delete pCounterMutex; + ObjectCounter::s_pObjectCounter = 0; +} + +ObjectCounter::ObjectCounter() +{ +} + +ObjectCounter::~ObjectCounter() +{ + s_bDeleted = true; +} + +ObjectCounter * ObjectCounter::get() +{ + if (!s_pObjectCounter) { + if (s_bDeleted) { + // This is _after_ the deleteObjectCounter has been called. + return 0; + } else { + s_pObjectCounter = new ObjectCounter; + pCounterMutex = new boost::mutex; + atexit(deleteObjectCounter); + } + } + return s_pObjectCounter; +} + +void ObjectCounter::incRef(const std::type_info* pType) +{ +#ifdef DEBUG_ALLOC + lock_guard Lock(*pCounterMutex); + TypeMap::iterator MapEntry = m_TypeMap.find(pType); + if (MapEntry == m_TypeMap.end()) { + m_TypeMap[pType] = 1; + } else { + (MapEntry->second)++; + } +// cerr << "incRef " << demangle(pType->name()) << ":" << m_TypeMap[pType] << endl; +#endif +} + +void ObjectCounter::decRef(const std::type_info* pType) +{ +#ifdef DEBUG_ALLOC + if (!this) { + // This happens if there are counted static objects that are deleted after + // s_pObjectCounter has been deleted. + return; + } + lock_guard Lock(*pCounterMutex); + TypeMap::iterator MapEntry = m_TypeMap.find(pType); + if (MapEntry == m_TypeMap.end()) { + cerr << "ObjectCounter for " << demangle(pType->name()) + << " does not exist." << endl; + // Can't decref a type that hasn't been incref'd. + AVG_ASSERT(false); + } else { + (MapEntry->second)--; + if (MapEntry->second < 0) { + cerr << "ObjectCounter: refcount for " << + demangle(MapEntry->first->name()) << + " < 0" << endl; + AVG_ASSERT(false); + } + } +// cerr << "decRef " << demangle(pType->name()) << ":" << MapEntry->second << endl; +#endif +} + +int ObjectCounter::getCount(const std::type_info* pType) +{ + TypeMap::iterator MapEntry = m_TypeMap.find(pType); + if (MapEntry == m_TypeMap.end()) { + return 0; + } else { + return MapEntry->second; + } + +} + +std::string ObjectCounter::dump() +{ + stringstream ss; + ss << "Object dump: " << endl; + TypeMap::iterator it; + vector<string> strings; + for (it = m_TypeMap.begin(); it != m_TypeMap.end(); ++it) { + stringstream tempStream; + if (it->second > 0) { + tempStream << " " << demangle(it->first->name()) << ": " << it->second; + strings.push_back(tempStream.str()); + } + } + sort(strings.begin(), strings.end()); + for (vector<string>::iterator it=strings.begin(); it != strings.end(); ++it) { + ss << *it << endl; + } + return ss.str(); +} + +string ObjectCounter::demangle(string s) +{ + int rc; + string sResult; +#ifdef _WIN32 + char szDemangledName[2048]; + rc = int(UnDecorateSymbolName(s.c_str(), szDemangledName, sizeof(szDemangledName), + UNDNAME_COMPLETE)); + if (rc) { + sResult = szDemangledName; + } else { + int error = GetLastError(); + printf("UnDecorateSymbolName returned error %d\n", error); + sResult = s; + } +#else + char * pszDemangled = abi::__cxa_demangle(s.c_str(), 0, 0, &rc); + if (rc) { + sResult = s; + } else { + sResult = pszDemangled; + } + if (pszDemangled) { + free(pszDemangled); + } +#endif + return sResult; +} + +TypeMap ObjectCounter::getObjectCount(){ + return m_TypeMap; +} + +} |