summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/qregexp.cpp117
1 files changed, 76 insertions, 41 deletions
diff --git a/src/tools/qregexp.cpp b/src/tools/qregexp.cpp
index 5c0fac766..0cc36c1d0 100644
--- a/src/tools/qregexp.cpp
+++ b/src/tools/qregexp.cpp
@@ -3211,39 +3211,86 @@ struct TQRegExpPrivate
};
#ifndef TQT_NO_REGEXP_OPTIM
-static TQSingleCleanupHandler<TQCache<TQRegExpEngine> > cleanup_cache;
-# ifndef TQT_THREAD_SUPPORT
-static TQCache<TQRegExpEngine> *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<TQRegExpEngine> *getCache() {
+ if ( wasDestroyed ) {
+ return nullptr;
+ }
+
+ static EngineCacheKeaper self;
+ return self.doGetCache();
+ }
+private:
+
+ TQCache<TQRegExpEngine> *doGetCache() {
+# ifdef TQT_THREAD_SUPPORT
+ TQThreadInstance *currentThread = TQThreadInstance::current();
+ if (!currentThread) {
+ return nullptr;
+ }
+ TQCache<TQRegExpEngine> *engineCache = engineCaches.localData();
+# endif // TQT_THREAD_SUPPORT
+
+ if ( engineCache == 0 ) {
+ engineCache = new TQCache<TQRegExpEngine>;
+ engineCache->setAutoDelete( TRUE );
+# ifdef TQT_THREAD_SUPPORT
+ engineCaches.setLocalData(engineCache);
+# else
+ static TQSingleCleanupHandler<TQCache<TQRegExpEngine>> cleanup_cache;
+ cleanup_cache.set( &engineCache );
+# endif // !TQT_THREAD_SUPPORT
+ }
+
+ return engineCache;
+ }
+
+# ifdef TQT_THREAD_SUPPORT
+ TQThreadStorage<TQCache<TQRegExpEngine>*> engineCaches;
+# else
+ TQCache<TQRegExpEngine> *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<TQCache<TQRegExpEngine> *> engineCaches;
- TQCache<TQRegExpEngine> *engineCache = 0;
- TQThreadInstance *currentThread = TQThreadInstance::current();
- if (currentThread)
- engineCache = engineCaches.localData();
-#endif // TQT_THREAD_SUPPORT
+#ifndef TQT_NO_REGEXP_OPTIM
+ TQCache<TQRegExpEngine> *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<TQRegExpEngine>;
- 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