diff options
Diffstat (limited to 'cpp/src/Ice/FactoryTable.cpp')
-rw-r--r-- | cpp/src/Ice/FactoryTable.cpp | 149 |
1 files changed, 123 insertions, 26 deletions
diff --git a/cpp/src/Ice/FactoryTable.cpp b/cpp/src/Ice/FactoryTable.cpp index d3307afa8bd..15904de2c0f 100644 --- a/cpp/src/Ice/FactoryTable.cpp +++ b/cpp/src/Ice/FactoryTable.cpp @@ -10,53 +10,150 @@ #include <Ice/FactoryTable.h> #include <Ice/UserExceptionFactory.h> -namespace IceInternal -{ +#ifdef __APPLE__ +# include <dlfcn.h> +#endif // -// Single global instance of the factory table for non-local -// exceptions and non-abstract classes. +// Add a factory to the exception factory table. +// If the factory is present already, increment its reference count. // -ICE_DECLSPEC_EXPORT FactoryTableDef* factoryTable; - +void +IceInternal::FactoryTable::addExceptionFactory(const std::string& t, const IceInternal::UserExceptionFactoryPtr& f) +{ + IceUtil::Mutex::Lock lock(_m); + EFTable::iterator i = _eft.find(t); + if(i == _eft.end()) + { + _eft[t] = EFPair(f, 1); + } + else + { + i->second.second++; + } } -namespace +// +// Return the exception factory for a given type ID +// +IceInternal::UserExceptionFactoryPtr +IceInternal::FactoryTable::getExceptionFactory(const std::string& t) const { + IceUtil::Mutex::Lock lock(_m); + EFTable::const_iterator i = _eft.find(t); +#ifdef __APPLE__ + if(i == _eft.end()) + { + lock.release(); -static int initCount = 0; // Initialization count -IceUtil::StaticMutex initCountMutex = ICE_STATIC_MUTEX_INITIALIZER; + // + // Try to find the symbol, if found this should trigger the + // object static constructors to be called. + // + std::string symbol = "__F"; + for(std::string::const_iterator p = t.begin(); p != t.end(); ++p) + { + symbol += ((*p) == ':') ? '_' : *p; + } + symbol += "__initializer"; + dlsym(RTLD_DEFAULT, symbol.c_str()); + lock.acquire(); + i = _eft.find(t); + } +#endif + return i != _eft.end() ? i->second.first : IceInternal::UserExceptionFactoryPtr(); } // -// This constructor initializes the single global -// IceInternal::factoryTable instance from the outside (if it hasn't -// been initialized yet). The constructor here is triggered by a -// file-static instance of FactoryTable in each slice2cpp-generated -// header file that uses non-local exceptions or non-abstract classes. -// This ensures that IceInternal::factoryTable is always initialized -// before it is used. +// Remove a factory from the exception factory table. If the factory +// is not present, do nothing; otherwise, decrement the factory's +// reference count; if the count drops to zero, remove the factory's +// entry from the table. // -IceInternal::FactoryTable::FactoryTable() +void +IceInternal::FactoryTable::removeExceptionFactory(const std::string& t) { - IceUtil::StaticMutex::Lock lock(initCountMutex); - if(0 == initCount++) + IceUtil::Mutex::Lock lock(_m); + EFTable::iterator i = _eft.find(t); + if(i != _eft.end()) { - factoryTable = new FactoryTableDef; + if(--i->second.second == 0) + { + _eft.erase(i); + } } } // -// The destructor decrements the reference count and, once the -// count drops to zero, deletes the table. +// Add a factory to the object factory table. // -IceInternal::FactoryTable::~FactoryTable() +void +IceInternal::FactoryTable::addObjectFactory(const std::string& t, const Ice::ObjectFactoryPtr& f) { - IceUtil::StaticMutex::Lock lock(initCountMutex); - if(0 == --initCount) + IceUtil::Mutex::Lock lock(_m); + OFTable::iterator i = _oft.find(t); + if(i == _oft.end()) + { + _oft[t] = OFPair(f, 1); + } + else { - delete factoryTable; + i->second.second++; } } + +// +// Return the object factory for a given type ID +// +Ice::ObjectFactoryPtr +IceInternal::FactoryTable::getObjectFactory(const std::string& t) const +{ + IceUtil::Mutex::Lock lock(_m); + OFTable::const_iterator i = _oft.find(t); +#ifdef __APPLE__ + if(i == _oft.end()) + { + lock.release(); + + // + // Try to find the symbol, if found this should trigger the + // object static constructors to be called. + // + std::string symbol = "__F"; + for(std::string::const_iterator p = t.begin(); p != t.end(); ++p) + { + symbol += ((*p) == ':') ? '_' : *p; + } + symbol += "__initializer"; + dlsym(RTLD_DEFAULT, symbol.c_str()); + + lock.acquire(); + + i = _oft.find(t); + } +#endif + return i != _oft.end() ? i->second.first : Ice::ObjectFactoryPtr(); +} + +// +// Remove a factory from the object factory table. If the factory +// is not present, do nothing; otherwise, decrement the factory's +// reference count if the count drops to zero, remove the factory's +// entry from the table. +// +void +IceInternal::FactoryTable::removeObjectFactory(const std::string& t) +{ + IceUtil::Mutex::Lock lock(_m); + OFTable::iterator i = _oft.find(t); + if(i != _oft.end()) + { + if(--i->second.second == 0) + { + _oft.erase(i); + } + } +} + |