summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/CommunicatorI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Ice/CommunicatorI.cpp')
-rw-r--r--cpp/src/Ice/CommunicatorI.cpp78
1 files changed, 77 insertions, 1 deletions
diff --git a/cpp/src/Ice/CommunicatorI.cpp b/cpp/src/Ice/CommunicatorI.cpp
index 731576cb23c..52f4bd86d6c 100644
--- a/cpp/src/Ice/CommunicatorI.cpp
+++ b/cpp/src/Ice/CommunicatorI.cpp
@@ -22,11 +22,19 @@
#include <Ice/LoggerUtil.h>
#include <Ice/LocalException.h>
#include <Ice/DefaultsAndOverrides.h>
+#include <Ice/TraceLevels.h>
+#include <IceUtil/GC.h>
using namespace std;
using namespace Ice;
using namespace IceInternal;
+int Ice::CommunicatorI::_communicatorCount = 0;
+Ice::CommunicatorI::GarbageCollectorStats Ice::CommunicatorI::_gcStats;
+int Ice::CommunicatorI::_gcTraceLevel;
+string Ice::CommunicatorI::_gcTraceCat;
+LoggerPtr Ice::CommunicatorI::_gcLogger;
+
void
Ice::CommunicatorI::destroy()
{
@@ -41,7 +49,39 @@ Ice::CommunicatorI::destroy()
instance = _instance;
}
}
-
+
+ bool last;
+ {
+ IceUtil::RecMutex::Lock sync(*this);
+ last = (--_communicatorCount == 0);
+ }
+
+ if(last)
+ {
+ //
+ // Wait for the collector thread to stop if this is the last communicator
+ // to be destroyed.
+ //
+ theCollector->stop();
+ }
+
+ theCollector->collectGarbage(); // Collect whenever a communicator is destroyed.
+
+ if(last)
+ {
+ if(_gcTraceLevel)
+ {
+ Trace out(_gcLogger, _gcTraceCat);
+ out << "totals: " << _gcStats.collected << "/" << _gcStats.examined << ", "
+ << _gcStats.msec << "ms" << ", " << _gcStats.runs << " run";
+ if(_gcStats.runs != 1)
+ {
+ out << "s";
+ }
+ }
+ _gcLogger = 0;
+ }
+
if(instance)
{
instance->destroy();
@@ -284,6 +324,25 @@ Ice::CommunicatorI::CommunicatorI(int& argc, char* argv[], const PropertiesPtr&
throw;
}
__setNoDelete(false);
+
+ {
+ //
+ // If this is the first communicator that is created, use that communicator's
+ // property settings to determine whether to start the garbage collector.
+ // We remember that communicator's trace and logger settings so the garbage
+ // collector can continue to log messages even if the first communicator that
+ // is created isn't the last communicator to be destroyed.
+ //
+ IceUtil::RecMutex::Lock sync(*this);
+ if(++_communicatorCount == 1)
+ {
+ _gcTraceLevel = _instance->traceLevels()->gc;
+ _gcTraceCat = _instance->traceLevels()->gcCat;
+ _gcLogger = _instance->logger();
+ theCollector = new IceUtil::GC(properties->getPropertyAsInt("Ice.GC.Interval"), printGCStats);
+ theCollector->start();
+ }
+ }
}
Ice::CommunicatorI::~CommunicatorI()
@@ -313,3 +372,20 @@ Ice::CommunicatorI::finishSetup(int& argc, char* argv[])
{
_instance->finishSetup(argc, argv);
}
+
+void
+Ice::CommunicatorI::printGCStats(const ::IceUtil::GCStats& stats)
+{
+ if(_gcTraceLevel)
+ {
+ if(_gcTraceLevel > 1)
+ {
+ Trace out(_gcLogger, _gcTraceCat);
+ out << stats.collected << "/" << stats.examined << ", " << stats.msec << "ms";
+ }
+ ++_gcStats.runs;
+ _gcStats.examined += stats.examined;
+ _gcStats.collected += stats.collected;
+ _gcStats.msec += stats.msec;
+ }
+}