diff options
Diffstat (limited to 'cpp/src/Ice/CommunicatorI.cpp')
-rw-r--r-- | cpp/src/Ice/CommunicatorI.cpp | 78 |
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; + } +} |