From 750dbd3bd52f40b4a733a8cfe0c7611e13e4ddae Mon Sep 17 00:00:00 2001 From: Khaled Noaman <knoaman@apache.org> Date: Fri, 17 Oct 2003 16:44:34 +0000 Subject: [PATCH] Fix multithreading problem. git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@175282 13f79535-47bb-0310-9956-ffa450edef68 --- src/xercesc/util/regx/RangeTokenMap.cpp | 61 ++++++++++++++----------- src/xercesc/util/regx/TokenFactory.cpp | 53 ++++++++++++++++++++- src/xercesc/util/regx/TokenFactory.hpp | 6 ++- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/xercesc/util/regx/RangeTokenMap.cpp b/src/xercesc/util/regx/RangeTokenMap.cpp index 546b68ea0..1cba3c066 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 ac78f7cad..df0da4ccc 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 8e2b7237b..06ce011ae 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; -- GitLab