summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/kernel/ntqthread.h1
-rw-r--r--src/kernel/qapplication.cpp24
-rw-r--r--src/kernel/qthread_unix.cpp5
-rw-r--r--src/tools/qthreadinstance_p.h2
-rw-r--r--src/tools/qthreadstorage_unix.cpp17
5 files changed, 47 insertions, 2 deletions
diff --git a/src/kernel/ntqthread.h b/src/kernel/ntqthread.h
index 695a61fb7..0b38e5a33 100644
--- a/src/kernel/ntqthread.h
+++ b/src/kernel/ntqthread.h
@@ -120,6 +120,7 @@ protected:
private:
TQThreadInstance * d;
friend class TQThreadInstance;
+ friend class TQThreadStorageData;
friend class TQCoreApplicationThread;
friend class TQApplication;
friend class TQEventLoop;
diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp
index fbdb9330c..e8658cdab 100644
--- a/src/kernel/qapplication.cpp
+++ b/src/kernel/qapplication.cpp
@@ -542,12 +542,19 @@ TQClipboard *tqt_clipboard = 0; // global clipboard object
TQWidgetList * tqt_modal_stack=0; // stack of modal widgets
#ifdef TQT_THREAD_SUPPORT
+
// thread wrapper for the main() thread
class TQCoreApplicationThread : public TQThread
{
public:
inline TQCoreApplicationThread()
{
+#ifdef QT_CHECK_STATE
+ if ( tqt_gui_thread_self )
+ tqWarning( "TQCoreApplicationThread: there should be exactly one main thread object" );
+#endif
+ tqt_gui_thread_self = this;
+
TQThreadInstance::setCurrentThread(this);
// thread should be running and not finished for the lifetime
@@ -556,11 +563,19 @@ public:
d->finished = false;
d->eventLoop = NULL;
}
+
inline ~TQCoreApplicationThread()
{
+ tqt_gui_thread_self = nullptr;
+
// avoid warning from TQThread
d->running = false;
+ // do some cleanup, namely clean up the thread-local storage associated with the GUI thread
+ TQThreadInstance::finishGuiThread(d);
}
+
+ static TQCoreApplicationThread* self() { return tqt_gui_thread_self; }
+
private:
inline void run()
{
@@ -568,10 +583,15 @@ private:
// only so that we can instantiate the object
tqFatal("TQCoreApplicationThread: internal error");
}
+
+ static TQCoreApplicationThread* tqt_gui_thread_self;
};
+TQCoreApplicationThread* TQCoreApplicationThread::tqt_gui_thread_self = nullptr;
+
+// construct exactly one instance of the core thread with static storage duration. Do it static
+// rather than in the heap as we need it to be properly destroyed on the exit from the program.
static TQCoreApplicationThread tqt_main_thread;
-static TQThread *mainThread() { return &tqt_main_thread; }
#endif
// Definitions for posted events
@@ -1035,7 +1055,7 @@ TQApplication::TQApplication(Display *dpy, int argc, char **argv,
#ifdef TQT_THREAD_SUPPORT
TQThread* TQApplication::guiThread() {
- return mainThread();
+ return TQCoreApplicationThread::self();
}
bool TQApplication::isGuiThread() {
diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp
index 7a6bc3393..6a6f81b7f 100644
--- a/src/kernel/qthread_unix.cpp
+++ b/src/kernel/qthread_unix.cpp
@@ -180,6 +180,11 @@ void TQThreadInstance::finish( void * )
}
}
+void TQThreadInstance::finishGuiThread(TQThreadInstance *d) {
+ TQThreadStorageData::finish( d->thread_storage );
+ d->thread_storage = 0;
+}
+
TQMutex *TQThreadInstance::mutex() const
{
return qt_thread_mutexpool ? qt_thread_mutexpool->get( (void *) this ) : 0;
diff --git a/src/tools/qthreadinstance_p.h b/src/tools/qthreadinstance_p.h
index 14f0de591..076c2ba19 100644
--- a/src/tools/qthreadinstance_p.h
+++ b/src/tools/qthreadinstance_p.h
@@ -100,6 +100,8 @@ public:
static void finish( TQThreadInstance * );
#endif // Q_OS_WIN32
+ static void finishGuiThread( TQThreadInstance *d );
+
TQEventLoop* eventLoop;
int cleanupType;
bool disableThreadPostedEvents : 1;
diff --git a/src/tools/qthreadstorage_unix.cpp b/src/tools/qthreadstorage_unix.cpp
index d53f6fb6e..86192868e 100644
--- a/src/tools/qthreadstorage_unix.cpp
+++ b/src/tools/qthreadstorage_unix.cpp
@@ -38,6 +38,8 @@
#ifdef TQT_THREAD_SUPPORT
+#include "ntqapplication.h"
+#include "ntqthread.h"
#include "qplatformdefs.h"
#include "ntqthreadstorage.h"
@@ -88,6 +90,21 @@ TQThreadStorageData::TQThreadStorageData( void (*func)( void * ) )
TQThreadStorageData::~TQThreadStorageData()
{
+ // The Gui thread has static storage duration, TQThreadStorage are almost always static (it's
+ // technically possible to allocate those in the heap, but it's quite unusual). It's impossible
+ // to predict whichever of those one gets destroyed first, but usually it's a TQThreadStorage.
+ // In that case we have to do the cleanup of its storage ourself as it won't be possible after
+ // nullifying the destructor below.
+ TQThread *guiThread = TQApplication::guiThread();
+ if (guiThread) {
+ TQThreadInstance *d = guiThread->d;
+ TQMutexLocker locker( d->mutex() );
+ if (d->thread_storage && d->thread_storage[id]) {
+ thread_storage_usage[id].func( d->thread_storage[id] );
+ d->thread_storage[id] = nullptr;
+ }
+ }
+
pthread_mutex_lock( &thread_storage_mutex );
thread_storage_usage[id].used = FALSE;
thread_storage_usage[id].func = 0;