summaryrefslogtreecommitdiff
path: root/src/VBox
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2016-05-13 13:06:26 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2016-05-13 13:06:26 +0000
commit17ba8669ca62d48fb05976f28fe6a4dad5ad7c51 (patch)
tree501745ab7a3fda8bd1b43c4608398214b1413184 /src/VBox
parentcbb8f9ce8d6c19b65a6f1fbd49d18c4fbabac81e (diff)
downloadVirtualBox-svn-17ba8669ca62d48fb05976f28fe6a4dad5ad7c51.tar.gz
Main/VirtualBoxBase: Add code for collecting information about how many API objects of each component type are currently around and how many have been created ever. While working on this the tiny bug in the event code was found (harmless, as before VirtualBoxBase::BaseFinalRelease was idempotent, but now no longer acceptable)
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@60977 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src/VBox')
-rw-r--r--src/VBox/Main/idl/comimpl.xsl2
-rw-r--r--src/VBox/Main/include/VirtualBoxBase.h42
-rw-r--r--src/VBox/Main/src-all/VirtualBoxBase.cpp108
3 files changed, 132 insertions, 20 deletions
diff --git a/src/VBox/Main/idl/comimpl.xsl b/src/VBox/Main/idl/comimpl.xsl
index a6cb8eb7511..dd205b9c8a5 100644
--- a/src/VBox/Main/idl/comimpl.xsl
+++ b/src/VBox/Main/idl/comimpl.xsl
@@ -506,7 +506,7 @@
}
void FinalRelease()
{
- mEvent->FinalRelease();
+ uninit();
BaseFinalRelease();
}
STDMETHOD(COMGETTER(Type))(VBoxEventType_T *aType)
diff --git a/src/VBox/Main/include/VirtualBoxBase.h b/src/VBox/Main/include/VirtualBoxBase.h
index 1b6701ec353..64fad41d974 100644
--- a/src/VBox/Main/include/VirtualBoxBase.h
+++ b/src/VBox/Main/include/VirtualBoxBase.h
@@ -698,23 +698,8 @@ protected:
ComPtr<IUnknown> m_pUnkMarshaler;
#endif
- HRESULT BaseFinalConstruct()
- {
-#ifdef RT_OS_WINDOWS
- return CoCreateFreeThreadedMarshaler(this, //GetControllingUnknown(),
- m_pUnkMarshaler.asOutParam());
-#else
- return S_OK;
-#endif
- }
-
- void BaseFinalRelease()
- {
-#ifdef RT_OS_WINDOWS
- m_pUnkMarshaler.setNull();
-#endif
- }
-
+ HRESULT BaseFinalConstruct();
+ void BaseFinalRelease();
public:
VirtualBoxBase();
@@ -818,8 +803,31 @@ private:
/** User-level object lock for subclasses */
mutable RWLockHandle *mObjectLock;
+
+ /** Slot of this object in the saFactoryStats array */
+ uint32_t iFactoryStat;
};
+/** Structure for counting the currently existing and ever created objects
+ * for each component name. */
+typedef struct CLASSFACTORY_STAT
+{
+ const char *psz;
+ uint64_t current;
+ uint64_t overall;
+} CLASSFACTORY_STAT;
+
+/** Maximum number of component names to deal with. There will be debug
+ * assertions if the value is too low. Since the table is global and its
+ * entries are reasonably small, it's not worth squeezing out the last bit. */
+#define CLASSFACTORYSTATS_MAX 128
+
+/* global variables (defined in VirtualBoxBase.cpp) */
+extern CLASSFACTORY_STAT g_aClassFactoryStats[CLASSFACTORYSTATS_MAX];
+extern RWLockHandle *g_pClassFactoryStatsLock;
+
+extern void APIDumpComponentFactoryStats();
+
/**
* Dummy macro that is used to shut down Qt's lupdate tool warnings in some
* situations. This macro needs to be present inside (better at the very
diff --git a/src/VBox/Main/src-all/VirtualBoxBase.cpp b/src/VBox/Main/src-all/VirtualBoxBase.cpp
index 18d49138586..dc8d937f1dc 100644
--- a/src/VBox/Main/src-all/VirtualBoxBase.cpp
+++ b/src/VBox/Main/src-all/VirtualBoxBase.cpp
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2014 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -47,17 +47,121 @@
//
////////////////////////////////////////////////////////////////////////////////
-VirtualBoxBase::VirtualBoxBase() : mState(this)
+CLASSFACTORY_STAT g_aClassFactoryStats[CLASSFACTORYSTATS_MAX] =
+{
+ { "--- totals ---", 0 },
+ { NULL, 0 }
+};
+
+RWLockHandle *g_pClassFactoryStatsLock = NULL;
+
+
+VirtualBoxBase::VirtualBoxBase() :
+ mState(this),
+ iFactoryStat(~0U)
{
mObjectLock = NULL;
+
+ if (!g_pClassFactoryStatsLock)
+ {
+ RWLockHandle *lock = new RWLockHandle(LOCKCLASS_OBJECTSTATE);
+ if (!ASMAtomicCmpXchgPtr(&g_pClassFactoryStatsLock, lock, NULL))
+ delete lock;
+ }
+ Assert(g_pClassFactoryStatsLock);
}
VirtualBoxBase::~VirtualBoxBase()
{
+ Assert(iFactoryStat == ~0U);
if (mObjectLock)
delete mObjectLock;
}
+HRESULT VirtualBoxBase::BaseFinalConstruct()
+{
+ Assert(iFactoryStat == ~0U);
+ if (g_pClassFactoryStatsLock)
+ {
+ AutoWriteLock alock(g_pClassFactoryStatsLock COMMA_LOCKVAL_SRC_POS);
+ g_aClassFactoryStats[0].current++;
+ g_aClassFactoryStats[0].overall++;
+ const char *pszName = getComponentName();
+ uint32_t i = 1;
+ while (i < CLASSFACTORYSTATS_MAX && g_aClassFactoryStats[i].psz)
+ {
+ if (g_aClassFactoryStats[i].psz == pszName)
+ break;
+ i++;
+ }
+ if (i < CLASSFACTORYSTATS_MAX)
+ {
+ if (!g_aClassFactoryStats[i].psz)
+ {
+ g_aClassFactoryStats[i].psz = pszName;
+ g_aClassFactoryStats[i].current = 0;
+ g_aClassFactoryStats[i].overall = 0;
+ }
+ iFactoryStat = i;
+ g_aClassFactoryStats[i].current++;
+ g_aClassFactoryStats[i].overall++;
+ }
+ else
+ AssertMsg(i < CLASSFACTORYSTATS_MAX, ("%u exhausts size of factory housekeeping array\n", i));
+ }
+ else
+ Assert(g_pClassFactoryStatsLock);
+
+#ifdef RT_OS_WINDOWS
+ return CoCreateFreeThreadedMarshaler(this, //GetControllingUnknown(),
+ m_pUnkMarshaler.asOutParam());
+#else
+ return S_OK;
+#endif
+}
+
+void VirtualBoxBase::BaseFinalRelease()
+{
+ if (g_pClassFactoryStatsLock)
+ {
+ AutoWriteLock alock(g_pClassFactoryStatsLock COMMA_LOCKVAL_SRC_POS);
+ g_aClassFactoryStats[0].current--;
+ const char *pszName = getComponentName();
+ if (iFactoryStat < CLASSFACTORYSTATS_MAX)
+ {
+ if (g_aClassFactoryStats[iFactoryStat].psz == pszName)
+ {
+ g_aClassFactoryStats[iFactoryStat].current--;
+ iFactoryStat = ~0U;
+ }
+ else
+ AssertMsgFailed(("could not find factory housekeeping array entry for %s (index %u contains %s)\n", pszName, iFactoryStat, g_aClassFactoryStats[iFactoryStat].psz));
+ }
+ else
+ AssertMsgFailed(("factory housekeeping array corruption, index %u is too large\n", iFactoryStat));
+ }
+ else
+ Assert(g_pClassFactoryStatsLock);
+
+#ifdef RT_OS_WINDOWS
+ m_pUnkMarshaler.setNull();
+#endif
+}
+
+void APIDumpComponentFactoryStats()
+{
+ if (g_pClassFactoryStatsLock)
+ {
+ AutoReadLock alock(g_pClassFactoryStatsLock COMMA_LOCKVAL_SRC_POS);
+ for (uint32_t i = 0; i < CLASSFACTORYSTATS_MAX && g_aClassFactoryStats[i].psz; i++)
+ LogRel(("CFS: component %-30s current %-10u total %-10u\n",
+ g_aClassFactoryStats[i].psz, g_aClassFactoryStats[i].current,
+ g_aClassFactoryStats[i].overall));
+ }
+ else
+ Assert(g_pClassFactoryStatsLock);
+}
+
/**
* This virtual method returns an RWLockHandle that can be used to
* protect instance data. This RWLockHandle is generally referred to