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 objects.

Signed-off-by: Alexander Golubev <fatzer2@gmail.com>
fix/various
Alexander Golubev 1 month ago
parent 10bd40911e
commit 65f9e94fca

@ -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

Loading…
Cancel
Save