summaryrefslogtreecommitdiff
path: root/src/base/ObjectCounter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/ObjectCounter.cpp')
-rw-r--r--src/base/ObjectCounter.cpp187
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;
+}
+
+}