diff --git a/src/xercesc/util/regx/RangeTokenMap.cpp b/src/xercesc/util/regx/RangeTokenMap.cpp index 546b68ea07343b45febcc8db89d0393b9824dd20..1cba3c0661090306ada60f80de9775ed65a1cde8 100644 --- a/src/xercesc/util/regx/RangeTokenMap.cpp +++ b/src/xercesc/util/regx/RangeTokenMap.cpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.6 2003/10/17 16:44:34 knoaman + * Fix multithreading problem. + * * Revision 1.5 2003/05/18 14:02:06 knoaman * Memory manager implementation: pass per instance manager. * @@ -168,43 +171,49 @@ RangeTokenMap::~RangeTokenMap() { // RangeTokenMap: Getter methods // --------------------------------------------------------------------------- RangeToken* RangeTokenMap::getRange(const XMLCh* const keyword, - const bool complement) { + const bool complement) { - if (fTokenRegistry == 0 || fRangeMap == 0 || fCategories == 0) - return 0; + if (fTokenRegistry == 0 || fRangeMap == 0 || fCategories == 0) + return 0; if (!fTokenRegistry->containsKey(keyword)) - return 0; + return 0; - RangeTokenElemMap* elemMap = 0; + RangeTokenElemMap* elemMap = fTokenRegistry->get(keyword); + RangeToken* rangeTok = elemMap->getRangeToken(complement); - // Use a faux scope to synchronize while we do this + if (!rangeTok) { XMLMutexLock lockInit(&fMutex); - elemMap = fTokenRegistry->get(keyword); - RangeToken* rangeTok = 0; - - if (elemMap->getRangeToken() == 0) { - - unsigned int categId = elemMap->getCategoryId(); - const XMLCh* categName = fCategories->getValueForId(categId); - RangeFactory* rangeFactory = fRangeMap->get(categName); - - if (rangeFactory == 0) - return 0; + // make sure that it was not created while we were locked + rangeTok = elemMap->getRangeToken(complement); - rangeFactory->buildRanges(); - } - - if (complement && ((rangeTok = elemMap->getRangeToken()) != 0)) { - elemMap->setRangeToken((RangeToken*) - RangeToken::complementRanges(rangeTok, fTokenFactory), - complement); - } + if (!rangeTok) + { + rangeTok = elemMap->getRangeToken(); + if (!rangeTok) + { + unsigned int categId = elemMap->getCategoryId(); + const XMLCh* categName = fCategories->getValueForId(categId); + RangeFactory* rangeFactory = fRangeMap->get(categName); + + if (rangeFactory == 0) + return 0; + + rangeFactory->buildRanges(); + rangeTok = elemMap->getRangeToken(); + } + + if (complement) + { + rangeTok = (RangeToken*) RangeToken::complementRanges(rangeTok, fTokenFactory); + elemMap->setRangeToken(rangeTok , complement); + } + } } - return (elemMap == 0) ? 0 : elemMap->getRangeToken(complement); + return rangeTok; } diff --git a/src/xercesc/util/regx/TokenFactory.cpp b/src/xercesc/util/regx/TokenFactory.cpp index ac78f7cad1cab1dd25bebaf11e36f17914152e57..df0da4ccc7e61b488768514f35841816fffd3489 100644 --- a/src/xercesc/util/regx/TokenFactory.cpp +++ b/src/xercesc/util/regx/TokenFactory.cpp @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.9 2003/10/17 16:44:34 knoaman + * Fix multithreading problem. + * * Revision 1.8 2003/05/18 14:02:06 knoaman * Memory manager implementation: pass per instance manager. * @@ -120,11 +123,59 @@ #include <xercesc/util/regx/BlockRangeFactory.hpp> #include <xercesc/util/regx/RangeTokenMap.hpp> #include <xercesc/util/regx/RegxDefs.hpp> +#include <xercesc/util/XMLRegisterCleanup.hpp> XERCES_CPP_NAMESPACE_BEGIN +// --------------------------------------------------------------------------- +// Static member data initialization +// --------------------------------------------------------------------------- bool TokenFactory::fRangeInitialized = false; +// --------------------------------------------------------------------------- +// Local static data +// --------------------------------------------------------------------------- +static bool sTokFactoryMutexRegistered = false; +static XMLMutex* sTokFactoryMutex = 0; +static XMLRegisterCleanup tokenFactoryMutexCleanup; + +// --------------------------------------------------------------------------- +// Local, static functions +// --------------------------------------------------------------------------- +// Cleanup for the TokenFactory mutex +void TokenFactory::reinitTokenFactoryMutex() +{ + delete sTokFactoryMutex; + sTokFactoryMutex = 0; + sTokFactoryMutexRegistered = false; +} + +// We need to fault in this mutex. But, since its used for synchronization +// itself, we have to do this the low level way using a compare and swap. +static XMLMutex& gTokenFactoryMutex() +{ + if (!sTokFactoryMutex) + { + XMLMutex* tmpMutex = new XMLMutex; + if (XMLPlatformUtils::compareAndSwap((void**)&sTokFactoryMutex, tmpMutex, 0)) + { + // Someone beat us to it, so let's clean up ours + delete tmpMutex; + } + + // Now lock it and try to register it + XMLMutexLock lock(sTokFactoryMutex); + + // If we got here first, then register it and set the registered flag + if (!sTokFactoryMutexRegistered) + { + tokenFactoryMutexCleanup.registerCleanup(TokenFactory::reinitTokenFactoryMutex); + sTokFactoryMutexRegistered = true; + } + } + return *sTokFactoryMutex; +} + // --------------------------------------------------------------------------- // TokenFactory: Constructors and Destructor // --------------------------------------------------------------------------- @@ -451,7 +502,7 @@ void TokenFactory::initializeRegistry() { // Use a faux scope to synchronize while we do this { - XMLMutexLock lockInit(&fMutex); + XMLMutexLock lockInit(&gTokenFactoryMutex()); if (!fRangeInitialized) { diff --git a/src/xercesc/util/regx/TokenFactory.hpp b/src/xercesc/util/regx/TokenFactory.hpp index 8e2b7237b1c97f1e6bb5c874d65cbacceed7d8d7..06ce011aee9658612f2f0dec75624e2cef225cb7 100644 --- a/src/xercesc/util/regx/TokenFactory.hpp +++ b/src/xercesc/util/regx/TokenFactory.hpp @@ -138,6 +138,11 @@ public: Token* getGraphemePattern(); MemoryManager* getMemoryManager() const; + // ----------------------------------------------------------------------- + // Notification that lazy data has been deleted + // ----------------------------------------------------------------------- + static void reinitTokenFactoryMutex(); + private: // ----------------------------------------------------------------------- // Unimplemented constructors and operators @@ -166,7 +171,6 @@ private: // Contains user created Token objects. Used for memory cleanup. // ----------------------------------------------------------------------- static bool fRangeInitialized; - XMLMutex fMutex; RefVectorOf<Token>* fTokens; Token* fEmpty; Token* fLineBegin;