TQRegExp: fix engine cache destruction ordering

In case there are static TQRegExp instances the regexp engine cash might
be destroyed before them; hence we need some special handling of
construction/destruction of the cache object(s).

Closes: https://mirror.git.trinitydesktop.org/gitea/TDE/tqt3/issues/142
Signed-off-by: Alexander Golubev <fatzer2@gmail.com>
fix/issue/142-r1
Alexander Golubev 7 months ago
parent fb0d62eec8
commit 3b9a744a7b

@ -3211,30 +3211,78 @@ struct TQRegExpPrivate
}; };
#ifndef TQT_NO_REGEXP_OPTIM #ifndef TQT_NO_REGEXP_OPTIM
static TQSingleCleanupHandler<TQCache<TQRegExpEngine> > cleanup_cache; namespace {
# ifndef TQT_THREAD_SUPPORT
static TQCache<TQRegExpEngine> *engineCache = 0; // 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 # 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 #endif // TQT_NO_REGEXP_OPTIM
static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern, static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern,
bool caseSensitive, bool deref ) bool caseSensitive, bool deref )
{ {
# ifdef TQT_THREAD_SUPPORT #ifndef TQT_NO_REGEXP_OPTIM
static TQThreadStorage<TQCache<TQRegExpEngine> *> engineCaches; TQCache<TQRegExpEngine> *engineCache = EngineCacheKeaper::getCache();
TQCache<TQRegExpEngine> *engineCache = 0; #endif // TQT_NO_REGEXP_OPTIM
TQThreadInstance *currentThread = TQThreadInstance::current();
if (currentThread)
engineCache = engineCaches.localData();
#endif // TQT_THREAD_SUPPORT
if ( !deref ) { if ( !deref ) {
#ifndef TQT_NO_REGEXP_OPTIM #ifndef TQT_NO_REGEXP_OPTIM
# ifdef TQT_THREAD_SUPPORT if ( engineCache ) {
if ( currentThread )
# endif
{
if ( engineCache != 0 ) {
eng = engineCache->take( pattern ); eng = engineCache->take( pattern );
if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { if ( eng == 0 || eng->caseSensitive() != caseSensitive ) {
delete eng; delete eng;
@ -3243,7 +3291,6 @@ static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern,
return; return;
} }
} }
}
#endif // TQT_NO_REGEXP_OPTIM #endif // TQT_NO_REGEXP_OPTIM
eng = new TQRegExpEngine( pattern, caseSensitive ); eng = new TQRegExpEngine( pattern, caseSensitive );
return; return;
@ -3251,19 +3298,7 @@ static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern,
if ( eng->deref() ) { if ( eng->deref() ) {
#ifndef TQT_NO_REGEXP_OPTIM #ifndef TQT_NO_REGEXP_OPTIM
# ifdef TQT_THREAD_SUPPORT if ( engineCache ) {
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() && if ( !pattern.isNull() &&
engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) engineCache->insert(pattern, eng, 4 + pattern.length() / 4) )
return; return;

Loading…
Cancel
Save