diff --git a/src/tools/qregexp.cpp b/src/tools/qregexp.cpp index 5c0fac76..0cc36c1d 100644 --- a/src/tools/qregexp.cpp +++ b/src/tools/qregexp.cpp @@ -3211,39 +3211,86 @@ struct TQRegExpPrivate }; #ifndef TQT_NO_REGEXP_OPTIM -static TQSingleCleanupHandler > cleanup_cache; -# ifndef TQT_THREAD_SUPPORT -static TQCache *engineCache = 0; +namespace { + +// Due to regexpEngine() is called from destructors (including destructors of static TQRegExp +// instances) it may cause it to try to resurrect the engine cache after it's been already +// destroyed, so we should keep an eye on it, hence we have a somewhat peculiar singleton here +// Yay! Handling destruction of statics is so much fun! >_< +class EngineCacheKeaper { +public: + static TQCache *getCache() { + if ( wasDestroyed ) { + return nullptr; + } + + static EngineCacheKeaper self; + return self.doGetCache(); + } +private: + + TQCache *doGetCache() { +# ifdef TQT_THREAD_SUPPORT + TQThreadInstance *currentThread = TQThreadInstance::current(); + if (!currentThread) { + return nullptr; + } + TQCache *engineCache = engineCaches.localData(); +# endif // TQT_THREAD_SUPPORT + + if ( engineCache == 0 ) { + engineCache = new TQCache; + engineCache->setAutoDelete( TRUE ); +# ifdef TQT_THREAD_SUPPORT + engineCaches.setLocalData(engineCache); +# else + static TQSingleCleanupHandler> cleanup_cache; + cleanup_cache.set( &engineCache ); +# endif // !TQT_THREAD_SUPPORT + } + + return engineCache; + } + +# ifdef TQT_THREAD_SUPPORT + TQThreadStorage*> engineCaches; +# else + TQCache *engineCache; # endif // TQT_THREAD_SUPPORT + + ~EngineCacheKeaper() { + wasDestroyed = TRUE; +# if !defined(TQT_THREAD_SUPPORT) + delete engineCache; +# endif // !defined(TQT_THREAD_SUPPORT) + } + static bool wasDestroyed; +}; + +bool EngineCacheKeaper::wasDestroyed = 0; + +} #endif // TQT_NO_REGEXP_OPTIM + static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern, bool caseSensitive, bool deref ) { -# ifdef TQT_THREAD_SUPPORT - static TQThreadStorage *> engineCaches; - TQCache *engineCache = 0; - TQThreadInstance *currentThread = TQThreadInstance::current(); - if (currentThread) - engineCache = engineCaches.localData(); -#endif // TQT_THREAD_SUPPORT +#ifndef TQT_NO_REGEXP_OPTIM + TQCache *engineCache = EngineCacheKeaper::getCache(); +#endif // TQT_NO_REGEXP_OPTIM if ( !deref ) { #ifndef TQT_NO_REGEXP_OPTIM -# ifdef TQT_THREAD_SUPPORT - if ( currentThread ) -# endif - { - if ( engineCache != 0 ) { - eng = engineCache->take( pattern ); - if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { - delete eng; - } else { - eng->ref(); - return; - } - } - } + if ( engineCache ) { + eng = engineCache->take( pattern ); + if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { + delete eng; + } else { + eng->ref(); + return; + } + } #endif // TQT_NO_REGEXP_OPTIM eng = new TQRegExpEngine( pattern, caseSensitive ); return; @@ -3251,23 +3298,11 @@ static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern, if ( eng->deref() ) { #ifndef TQT_NO_REGEXP_OPTIM -# ifdef TQT_THREAD_SUPPORT - if ( currentThread ) -# endif - { - if ( engineCache == 0 ) { - engineCache = new TQCache; - engineCache->setAutoDelete( TRUE ); -# ifdef TQT_THREAD_SUPPORT - engineCaches.setLocalData(engineCache); -# else - cleanup_cache.set( &engineCache ); -# endif // !TQT_THREAD_SUPPORT - } - if ( !pattern.isNull() && - engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) - return; - } + if ( engineCache ) { + if ( !pattern.isNull() && + engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) + return; + } #else Q_UNUSED( pattern ); #endif // TQT_NO_REGEXP_OPTIM