From aeefd3fe454bfaed093355278b1e2caa84bfd77a Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 30 Jun 2024 12:33:25 +0900 Subject: Rename threading nt* related files to equivalent tq* Signed-off-by: Michele Calgaro --- src/kernel/ntqt.h | 8 +- src/kernel/ntqthread.h | 147 ---------- src/kernel/qapplication.cpp | 6 +- src/kernel/qapplication_x11.cpp | 2 +- src/kernel/qeventloop.cpp | 4 +- src/kernel/qeventloop_unix.cpp | 2 +- src/kernel/qeventloop_unix_glib.cpp | 4 +- src/kernel/qeventloop_x11.cpp | 2 +- src/kernel/qeventloop_x11_glib.cpp | 4 +- src/kernel/qmetaobject.cpp | 2 +- src/kernel/qt_kernel.pri | 8 +- src/kernel/qthread.cpp | 271 ----------------- src/kernel/qthread_unix.cpp | 569 ------------------------------------ src/kernel/tqobject.cpp | 6 +- src/kernel/tqobject.h | 2 +- src/kernel/tqthread.cpp | 271 +++++++++++++++++ src/kernel/tqthread.h | 147 ++++++++++ src/kernel/tqthread_unix.cpp | 569 ++++++++++++++++++++++++++++++++++++ src/kernel/tqwidget.cpp | 2 +- 19 files changed, 1013 insertions(+), 1013 deletions(-) delete mode 100644 src/kernel/ntqthread.h delete mode 100644 src/kernel/qthread.cpp delete mode 100644 src/kernel/qthread_unix.cpp create mode 100644 src/kernel/tqthread.cpp create mode 100644 src/kernel/tqthread.h create mode 100644 src/kernel/tqthread_unix.cpp (limited to 'src/kernel') diff --git a/src/kernel/ntqt.h b/src/kernel/ntqt.h index 4dee12662..41b65486d 100644 --- a/src/kernel/ntqt.h +++ b/src/kernel/ntqt.h @@ -136,7 +136,7 @@ #include #include #include "tqptrvector.h" -#include "ntqmutex.h" +#include "tqmutex.h" #include #include #include "ntqguardedptr.h" @@ -178,7 +178,7 @@ #include #include #include -#include "ntqsemaphore.h" +#include "tqsemaphore.h" #include #include "ntqsocketdevice.h" #include @@ -236,7 +236,7 @@ #include #include "ntqtoolbar.h" #include -#include "ntqwaitcondition.h" +#include "tqwaitcondition.h" #include #include #include @@ -257,7 +257,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/kernel/ntqthread.h b/src/kernel/ntqthread.h deleted file mode 100644 index 0b38e5a33..000000000 --- a/src/kernel/ntqthread.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** Definition of TQThread class -** -** Created : 931107 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQTHREAD_H -#define TQTHREAD_H - -#if defined(TQT_THREAD_SUPPORT) - -#ifndef QT_H -#include "ntqwindowdefs.h" -#endif // QT_H - -#include - -class TQThreadInstance; - -class TQ_EXPORT TQThread : public TQt -{ -public: - static TQt::HANDLE currentThread(); - - static void initialize(); - static void cleanup(); - - static void exit(); - -#ifdef Q_QDOC - TQThread( unsigned int stackSize = 0 ); -#else - TQThread( unsigned int stackSize ); - TQThread(); -#endif - - virtual ~TQThread(); - - // default argument causes thread to block indefinately - bool wait( unsigned long time = ULONG_MAX ); - - enum Priority { - IdlePriority, - - LowestPriority, - LowPriority, - NormalPriority, - HighPriority, - HighestPriority, - - TimeCriticalPriority, - - InheritPriority - }; - -#ifdef Q_QDOC - void start( Priority = InheritPriority ); -#else - void start( Priority ); - void start(); -#endif - - void terminate(); - - bool finished() const; - bool running() const; - - enum CleanupType { - CleanupNone, - CleanupMergeObjects - }; - - CleanupType cleanupType() const; - void setCleanupType(CleanupType); - - bool threadPostedEventsDisabled() const; - void setThreadPostedEventsDisabled(bool); - -protected: - virtual void run() = 0; - - static void sleep( unsigned long ); - static void msleep( unsigned long ); - static void usleep( unsigned long ); - -private: - TQThreadInstance * d; - friend class TQThreadInstance; - friend class TQThreadStorageData; - friend class TQCoreApplicationThread; - friend class TQApplication; - friend class TQEventLoop; - -#if defined(TQ_DISABLE_COPY) - TQThread( const TQThread & ); - TQThread &operator=( const TQThread & ); -#endif // TQ_DISABLE_COPY - -public: - static TQThread* currentThreadObject(); -}; - -class TQ_EXPORT TQEventLoopThread : public TQThread -{ - public: - TQEventLoopThread(); - ~TQEventLoopThread(); - virtual void run(); -}; - -#endif // TQT_THREAD_SUPPORT - -#endif // TQTHREAD_H diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp index c6bde72a7..5297837cc 100644 --- a/src/kernel/qapplication.cpp +++ b/src/kernel/qapplication.cpp @@ -66,9 +66,9 @@ #include "qfontdata_p.h" #if defined(TQT_THREAD_SUPPORT) -# include "ntqmutex.h" -# include "ntqthread.h" -# include +# include "tqmutex.h" +# include "tqthread.h" +# include #endif // TQT_THREAD_SUPPORT #include diff --git a/src/kernel/qapplication_x11.cpp b/src/kernel/qapplication_x11.cpp index 33fa0ceca..cd65da67a 100644 --- a/src/kernel/qapplication_x11.cpp +++ b/src/kernel/qapplication_x11.cpp @@ -95,7 +95,7 @@ #include "qinternal_p.h" // shared double buffer cleanup #if defined(TQT_THREAD_SUPPORT) -# include "ntqthread.h" +# include "tqthread.h" #endif #if defined(QT_DEBUG) && defined(Q_OS_LINUX) diff --git a/src/kernel/qeventloop.cpp b/src/kernel/qeventloop.cpp index e08a1ee1c..ce0f2bc82 100644 --- a/src/kernel/qeventloop.cpp +++ b/src/kernel/qeventloop.cpp @@ -42,8 +42,8 @@ #include "tqdatetime.h" #ifdef TQT_THREAD_SUPPORT -# include "ntqthread.h" -# include "private/qthreadinstance_p.h" +# include "tqthread.h" +# include "private/tqthreadinstance_p.h" #endif /*! diff --git a/src/kernel/qeventloop_unix.cpp b/src/kernel/qeventloop_unix.cpp index 132279314..89e31da82 100644 --- a/src/kernel/qeventloop_unix.cpp +++ b/src/kernel/qeventloop_unix.cpp @@ -40,7 +40,7 @@ #include "ntqeventloop.h" #include "ntqapplication.h" #include "ntqbitarray.h" -#include "ntqmutex.h" +#include "tqmutex.h" #include #include diff --git a/src/kernel/qeventloop_unix_glib.cpp b/src/kernel/qeventloop_unix_glib.cpp index e65d49bb2..5d43a6efb 100644 --- a/src/kernel/qeventloop_unix_glib.cpp +++ b/src/kernel/qeventloop_unix_glib.cpp @@ -40,10 +40,10 @@ #include "ntqeventloop.h" #include "ntqapplication.h" #include "ntqbitarray.h" -#include "ntqmutex.h" +#include "tqmutex.h" #if defined(TQT_THREAD_SUPPORT) - #include "ntqthread.h" + #include "tqthread.h" #endif #include diff --git a/src/kernel/qeventloop_x11.cpp b/src/kernel/qeventloop_x11.cpp index 1ba3b21df..6905bac22 100644 --- a/src/kernel/qeventloop_x11.cpp +++ b/src/kernel/qeventloop_x11.cpp @@ -44,7 +44,7 @@ #include "qt_x11_p.h" #if defined(TQT_THREAD_SUPPORT) -# include "ntqmutex.h" +# include "tqmutex.h" #endif // TQT_THREAD_SUPPORT #include diff --git a/src/kernel/qeventloop_x11_glib.cpp b/src/kernel/qeventloop_x11_glib.cpp index a13dbeebf..b152d6a38 100644 --- a/src/kernel/qeventloop_x11_glib.cpp +++ b/src/kernel/qeventloop_x11_glib.cpp @@ -47,8 +47,8 @@ #include "qt_x11_p.h" #if defined(TQT_THREAD_SUPPORT) -# include "ntqmutex.h" -# include "ntqthread.h" +# include "tqmutex.h" +# include "tqthread.h" #endif // TQT_THREAD_SUPPORT #include diff --git a/src/kernel/qmetaobject.cpp b/src/kernel/qmetaobject.cpp index 70ed6b5d5..624c025d8 100644 --- a/src/kernel/qmetaobject.cpp +++ b/src/kernel/qmetaobject.cpp @@ -42,7 +42,7 @@ #include "ntqasciidict.h" #ifdef TQT_THREAD_SUPPORT -#include +#include #endif // TQT_THREAD_SUPPORT /*! diff --git a/src/kernel/qt_kernel.pri b/src/kernel/qt_kernel.pri index 446019b6e..c4690a3f6 100644 --- a/src/kernel/qt_kernel.pri +++ b/src/kernel/qt_kernel.pri @@ -77,7 +77,7 @@ kernel { $$KERNEL_H/ntqsound.h \ $$KERNEL_H/tqstyle.h \ $$KERNEL_H/tqstylesheet.h \ - $$KERNEL_H/ntqthread.h \ + $$KERNEL_H/tqthread.h \ $$KERNEL_H/tqtimer.h \ $$KERNEL_H/ntqurl.h \ $$KERNEL_H/ntqlocalfs.h \ @@ -127,7 +127,7 @@ kernel { $$KERNEL_CPP/qpainter_win.cpp \ $$KERNEL_CPP/qregion_win.cpp \ $$KERNEL_CPP/qsound_win.cpp \ - $$KERNEL_CPP/qthread_win.cpp \ + $$KERNEL_CPP/tqthread_win.cpp \ $$KERNEL_CPP/tqwidget_win.cpp \ $$KERNEL_CPP/qole_win.c \ $$KERNEL_CPP/qfontengine_win.cpp @@ -191,7 +191,7 @@ kernel { } unix:SOURCES += $$KERNEL_CPP/qprocess_unix.cpp \ - $$KERNEL_CPP/qthread_unix.cpp + $$KERNEL_CPP/tqthread_unix.cpp SOURCES += $$KERNEL_CPP/qabstractlayout.cpp \ $$KERNEL_CPP/qucomextra.cpp \ @@ -248,7 +248,7 @@ kernel { $$KERNEL_CPP/qsocketnotifier.cpp \ $$KERNEL_CPP/qsound.cpp \ $$KERNEL_CPP/tqstylesheet.cpp \ - $$KERNEL_CPP/qthread.cpp \ + $$KERNEL_CPP/tqthread.cpp \ $$KERNEL_CPP/tqtimer.cpp \ $$KERNEL_CPP/qurl.cpp \ $$KERNEL_CPP/qlocalfs.cpp \ diff --git a/src/kernel/qthread.cpp b/src/kernel/qthread.cpp deleted file mode 100644 index bb51e41fc..000000000 --- a/src/kernel/qthread.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/**************************************************************************** -** -** Cross-platform TQThread implementation. -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifdef TQT_THREAD_SUPPORT - -#include "qplatformdefs.h" - -#include "ntqthread.h" -#include "ntqeventloop.h" -#include - -#ifndef QT_H -# include "ntqapplication.h" -#endif // QT_H - - -/*! - \class TQThread ntqthread.h - \threadsafe - \brief The TQThread class provides platform-independent threads. - - \ingroup thread - \ingroup environment - - A TQThread represents a separate thread of control within the - program; it shares data with all the other threads within the - process but executes independently in the way that a separate - program does on a multitasking operating system. Instead of - starting in main(), TQThreads begin executing in run(). You inherit - run() to include your code. For example: - - \code - class MyThread : public TQThread { - - public: - - virtual void run(); - - }; - - void MyThread::run() - { - for( int count = 0; count < 20; count++ ) { - sleep( 1 ); - tqDebug( "Ping!" ); - } - } - - int main() - { - MyThread a; - MyThread b; - a.start(); - b.start(); - a.wait(); - b.wait(); - } - \endcode - - This will start two threads, each of which writes Ping! 20 times - to the screen and exits. The wait() calls at the end of main() are - necessary because exiting main() ends the program, unceremoniously - killing all other threads. Each MyThread stops executing when it - reaches the end of MyThread::run(), just as an application does - when it leaves main(). - - \sa \link threads.html Thread Support in TQt\endlink. -*/ - -/*! - \enum TQThread::Priority - - This enum type indicates how the operating system should schedule - newly created threads. - - \value IdlePriority scheduled only when no other threads are - running. - - \value LowestPriority scheduled less often than LowPriority. - \value LowPriority scheduled less often than NormalPriority. - - \value NormalPriority the default priority of the operating - system. - - \value HighPriority scheduled more often than NormalPriority. - \value HighestPriority scheduled more often then HighPriority. - - \value TimeCriticalPriority scheduled as often as possible. - - \value InheritPriority use the same priority as the creating - thread. This is the default. -*/ - -TQThread::TQThread() -{ -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( TQApplication::tqt_mutex ); -#endif // TQT_THREAD_SUPPORT - - d = new TQThreadInstance; - d->init(0); -} - -/*! - Constructs a new thread. The thread does not begin executing until - start() is called. - - If \a stackSize is greater than zero, the maximum stack size is - set to \a stackSize bytes, otherwise the maximum stack size is - automatically determined by the operating system. - - \warning Most operating systems place minimum and maximum limits - on thread stack sizes. The thread will fail to start if the stack - size is outside these limits. -*/ -TQThread::TQThread( unsigned int stackSize ) -{ - d = new TQThreadInstance; - d->init(stackSize); -} - -/*! - TQThread destructor. - - Note that deleting a TQThread object will not stop the execution of - the thread it represents. Deleting a running TQThread (i.e. - finished() returns FALSE) will probably result in a program crash. - You can wait() on a thread to make sure that it has finished. -*/ -TQThread::~TQThread() -{ - TQMutexLocker locker( d->mutex() ); - if ( d->running && !d->finished ) { -#ifdef QT_CHECK_STATE - tqWarning("TQThread object destroyed while thread is still running."); -#endif - - d->orphan = TRUE; - return; - } - - d->deinit(); - delete d; -} - -/*! - This function terminates the execution of the thread. The thread - may or may not be terminated immediately, depending on the - operating system's scheduling policies. Use TQThread::wait() - after terminate() for synchronous termination. - - When the thread is terminated, all threads waiting for the - the thread to finish will be woken up. - - \warning This function is dangerous, and its use is discouraged. - The thread can be terminated at any point in its code path. Threads - can be terminated while modifying data. There is no chance for - the thread to cleanup after itself, unlock any held mutexes, etc. - In short, use this function only if \e absolutely necessary. -*/ -void TQThread::terminate() -{ - TQMutexLocker locker( d->mutex() ); - if ( d->finished || !d->running ) - return; - d->terminate(); -} - -/*! - Returns TRUE if the thread is finished; otherwise returns FALSE. -*/ -bool TQThread::finished() const -{ - TQMutexLocker locker( d->mutex() ); - return d->finished; -} - -/*! - Returns TRUE if the thread is running; otherwise returns FALSE. -*/ -bool TQThread::running() const -{ - TQMutexLocker locker( d->mutex() ); - return d->running; -} - -/*! - Changes the way cross thread signals are handled - If disable is FALSE, signals emitted from this thread will be - posted to any other connected threads' event loops (default). - - If disable is TRUE, calls to emit from this thread - will immediately execute slots in another thread. - This mode of operation is inherently unsafe and is provided - solely to support thread management by a third party application. - */ -void TQThread::setThreadPostedEventsDisabled(bool disable) -{ - d->disableThreadPostedEvents = disable; -} - -/*! - Returns TRUE if thread posted events are disabled, FALSE if not - */ -bool TQThread::threadPostedEventsDisabled() const -{ - return d->disableThreadPostedEvents; -} - -/*! - \fn void TQThread::run() - - This method is pure virtual, and must be implemented in derived - classes in order to do useful work. Returning from this method - will end the execution of the thread. - - \sa wait() -*/ - -TQEventLoopThread::TQEventLoopThread() : TQThread() -{ - // -} - -TQEventLoopThread::~TQEventLoopThread() -{ - // -} - -void TQEventLoopThread::run() -{ - TQEventLoop* eventLoop = TQApplication::eventLoop(); - if (eventLoop) eventLoop->exec(); -} - -#endif // TQT_THREAD_SUPPORT diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp deleted file mode 100644 index be67e002d..000000000 --- a/src/kernel/qthread_unix.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/**************************************************************************** -** -** TQThread class for Unix -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#if defined(TQT_THREAD_SUPPORT) - -#include "qplatformdefs.h" - -typedef pthread_mutex_t Q_MUTEX_T; - -#include "ntqthread.h" -#include -#include -#include -#include -#include - -#include -#include - -#if defined(QT_USE_GLIBMAINLOOP) -#include -#endif // QT_USE_GLIBMAINLOOP - -static TQMutexPool *qt_thread_mutexpool = 0; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -typedef void*(*TQtThreadCallback)(void*); - -static pthread_once_t storage_key_once = PTHREAD_ONCE_INIT; -static pthread_key_t storage_key; -static void create_storage_key() -{ - pthread_key_create( &storage_key, NULL ); -} - -#if defined(Q_C_CALLBACKS) -} -#endif - - -/************************************************************************** - ** TQThreadInstance - *************************************************************************/ - -void TQThreadInstance::setCurrentThread(TQThread *thread) -{ - pthread_once(&storage_key_once, create_storage_key); - pthread_setspecific(storage_key, thread); -} - -TQThreadInstance *TQThreadInstance::current() -{ - TQThreadInstance *ret = NULL; - pthread_once( &storage_key_once, create_storage_key ); - TQThread *thread = (TQThread *) pthread_getspecific( storage_key ); - if (thread) { - ret = thread->d; - } - return ret; -} - -void TQThreadInstance::init(unsigned int stackSize) -{ - stacksize = stackSize; - args[0] = args[1] = 0; - thread_storage = 0; - finished = FALSE; - running = FALSE; - orphan = FALSE; - disableThreadPostedEvents = FALSE; - - pthread_cond_init(&thread_done, NULL); - thread_id = 0; - - eventLoop = 0; - cleanupType = TQThread::CleanupMergeObjects; - - // threads have not been initialized yet, do it now - if (! qt_thread_mutexpool) TQThread::initialize(); -} - -void TQThreadInstance::deinit() -{ - pthread_cond_destroy(&thread_done); -} - -void *TQThreadInstance::start( void *_arg ) -{ - void **arg = (void **) _arg; - -#if defined(QT_USE_GLIBMAINLOOP) - // This is the first time we have access to the native pthread ID of this newly created thread - ((TQThreadInstance*)arg[1])->thread_id = pthread_self(); -#endif // QT_USE_GLIBMAINLOOP - -#ifdef QT_DEBUG - tqDebug("TQThreadInstance::start: Setting thread storage to %p\n", (TQThread *) arg[0]); -#endif // QT_DEBUG - setCurrentThread( (TQThread *) arg[0] ); - - pthread_cleanup_push( TQThreadInstance::finish, arg[1] ); - pthread_testcancel(); - - ( (TQThread *) arg[0] )->run(); - - pthread_cleanup_pop( TRUE ); - return 0; -} - -void TQThreadInstance::finish( void * ) -{ - TQThreadInstance *d = current(); - - if ( ! d ) { -#ifdef QT_CHECK_STATE - tqWarning( "TQThread: internal error: zero data for running thread." ); -#endif // QT_CHECK_STATE - return; - } - -#ifdef QT_DEBUG - tqDebug("TQThreadInstance::finish: In TQThreadInstance::finish for thread %p\n", (TQThread*)d->args[0]); -#endif // QT_DEBUG - - TQApplication::threadTerminationHandler((TQThread*)d->args[0]); - - TQMutexLocker locker( d->mutex() ); - d->running = FALSE; - d->finished = TRUE; - d->args[0] = d->args[1] = 0; - - - TQThreadStorageData::finish( d->thread_storage ); - d->thread_storage = 0; - - d->thread_id = 0; - pthread_cond_broadcast(&d->thread_done); - - if (d->orphan) { - d->deinit(); - delete d; - } -} - -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; -} - -void TQThreadInstance::terminate() -{ - if ( ! thread_id ) return; - pthread_cancel( thread_id ); -} - -/************************************************************************** - ** TQThread - *************************************************************************/ - -/*! - This returns the thread handle of the currently executing thread. - - \warning The handle returned by this function is used for internal - purposes and should \e not be used in any application code. On - Windows, the returned value is a pseudo handle for the current - thread, and it cannot be used for numerical comparison. -*/ -TQt::HANDLE TQThread::currentThread() -{ - return (HANDLE) pthread_self(); -} - -/*! \internal - Initializes the TQThread system. -*/ -void TQThread::initialize() -{ - if ( ! tqt_global_mutexpool ) - tqt_global_mutexpool = new TQMutexPool( TRUE, 73 ); - if ( ! qt_thread_mutexpool ) - qt_thread_mutexpool = new TQMutexPool( FALSE, 127 ); -} - -/*! \internal - Cleans up the TQThread system. -*/ -void TQThread::cleanup() -{ - delete tqt_global_mutexpool; - delete qt_thread_mutexpool; - tqt_global_mutexpool = 0; - qt_thread_mutexpool = 0; -} - -/*! - Ends the execution of the calling thread and wakes up any threads - waiting for its termination. -*/ -void TQThread::exit() -{ - pthread_exit( 0 ); -} - -/* \internal - helper function to do thread sleeps, since usleep()/nanosleep() - aren't reliable enough (in terms of behavior and availability) -*/ -static void thread_sleep( struct timespec *ti ) -{ - pthread_mutex_t mtx; - pthread_cond_t cnd; - - pthread_mutex_init(&mtx, 0); - pthread_cond_init(&cnd, 0); - - pthread_mutex_lock( &mtx ); - (void) pthread_cond_timedwait( &cnd, &mtx, ti ); - pthread_mutex_unlock( &mtx ); - - pthread_cond_destroy( &cnd ); - pthread_mutex_destroy( &mtx ); -} - -/*! - System independent sleep. This causes the current thread to sleep - for \a secs seconds. -*/ -void TQThread::sleep( unsigned long secs ) -{ - struct timeval tv; - gettimeofday( &tv, 0 ); - struct timespec ti; - ti.tv_sec = tv.tv_sec + secs; - ti.tv_nsec = ( tv.tv_usec * 1000 ); - thread_sleep( &ti ); -} - -/*! - System independent sleep. This causes the current thread to sleep - for \a msecs milliseconds -*/ -void TQThread::msleep( unsigned long msecs ) -{ - struct timeval tv; - gettimeofday( &tv, 0 ); - struct timespec ti; - - ti.tv_nsec = ( tv.tv_usec + ( msecs % 1000 ) * 1000 ) * 1000; - ti.tv_sec = tv.tv_sec + ( msecs / 1000 ) + ( ti.tv_nsec / 1000000000 ); - ti.tv_nsec %= 1000000000; - thread_sleep( &ti ); -} - -/*! - System independent sleep. This causes the current thread to sleep - for \a usecs microseconds -*/ -void TQThread::usleep( unsigned long usecs ) -{ - struct timeval tv; - gettimeofday( &tv, 0 ); - struct timespec ti; - - ti.tv_nsec = ( tv.tv_usec + ( usecs % 1000000 ) ) * 1000; - ti.tv_sec = tv.tv_sec + ( usecs / 1000000 ) + ( ti.tv_nsec / 1000000000 ); - ti.tv_nsec %= 1000000000; - thread_sleep( &ti ); -} - -/*! - Begins execution of the thread by calling run(), which should be - reimplemented in a TQThread subclass to contain your code. The - operating system will schedule the thread according to the \a - priority argument. - - If you try to start a thread that is already running, this - function will wait until the the thread has finished and then - restart the thread. - - \sa Priority -*/ -void TQThread::start(Priority priority) -{ - TQMutexLocker locker( d->mutex() ); - - if ( d->running ) - pthread_cond_wait(&d->thread_done, &locker.mutex()->d->handle); - d->running = TRUE; - d->finished = FALSE; - - int ret; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0) -#if _POSIX_THREAD_PRIORITY_SCHEDULING == 0 && defined _SC_THREAD_PRIORITY_SCHEDULING - if (sysconf(_SC_THREAD_PRIORITY_SCHEDULING) > 0) -#endif - switch (priority) { - case InheritPriority: - { - pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); - break; - } - - default: - { - int sched_policy; - if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) { - // failed to get the scheduling policy, don't bother - // setting the priority - tqWarning("TQThread: cannot determine default scheduler policy"); - break; - } - - int prio_min = sched_get_priority_min(sched_policy); - int prio_max = sched_get_priority_max(sched_policy); - if (prio_min == -1 || prio_max == -1) { - // failed to get the scheduling parameters, don't - // bother setting the priority - tqWarning("TQThread: cannot determine scheduler priority range"); - break; - } - - int prio; - switch (priority) { - case IdlePriority: - prio = prio_min; - break; - - case HighestPriority: - prio = prio_max; - break; - - default: - // crudely scale our priority enum values to the prio_min/prio_max - prio = (((prio_max - prio_min) / TimeCriticalPriority) * - priority) + prio_min; - prio = TQMAX(prio_min, TQMIN(prio_max, prio)); - break; - } - - sched_param sp; - sp.sched_priority = prio; - - pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setschedparam(&attr, &sp); - break; - } - } -#endif // _POSIX_THREAD_PRIORITY_SCHEDULING - - if ( d->stacksize > 0 ) { -#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0) - ret = pthread_attr_setstacksize( &attr, d->stacksize ); -#else - ret = ENOSYS; // stack size not supported, automatically fail -#endif // _POSIX_THREAD_ATTR_STACKSIZE - - if ( ret ) { -#ifdef QT_CHECK_STATE - tqWarning( "TQThread::start: thread stack size error: %s", strerror( ret ) ) ; -#endif // QT_CHECK_STATE - - // we failed to set the stacksize, and as the documentation states, - // the thread will fail to run... - d->running = FALSE; - d->finished = FALSE; - return; - } - } - - d->args[0] = this; - d->args[1] = d; -#if defined(QT_USE_GLIBMAINLOOP) - // The correct thread_id is set in TQThreadInstance::start using the value of d->args[1] - d->thread_id = 0; - - // glib versions < 2.32.0 requires threading system initialization call - #if GLIB_CHECK_VERSION(2, 32, 0) - GThread* glib_thread_handle = g_thread_new( NULL, (GThreadFunc)TQThreadInstance::start, d->args ); - #else - if( !g_thread_get_initialized() ); - g_thread_init(NULL); - GThread* glib_thread_handle = g_thread_create((GThreadFunc)TQThreadInstance::start, d->args, false, NULL); - #endif - - if (glib_thread_handle) { - ret = 0; - } - else { - ret = -1; - } -#else // QT_USE_GLIBMAINLOOP - ret = pthread_create( &d->thread_id, &attr, (TQtThreadCallback)TQThreadInstance::start, d->args ); -#if defined (Q_OS_HPUX) - if (ret == EPERM) { - pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); - ret = pthread_create(&d->thread_id, &attr, (TQtThreadCallback)TQThreadInstance::start, d->args); - } -#endif - pthread_attr_destroy( &attr ); -#endif // QT_USE_GLIBMAINLOOP - - if ( ret ) { -#ifdef QT_CHECK_STATE - tqWarning( "TQThread::start: thread creation error: %s", strerror( ret ) ); -#endif // QT_CHECK_STATE - - d->running = FALSE; - d->finished = FALSE; - d->args[0] = d->args[1] = 0; - } -} - -void TQThread::start() -{ - start(InheritPriority); -} - -/*! - A thread calling this function will block until either of these - conditions is met: - - \list - \i The thread associated with this TQThread object has finished - execution (i.e. when it returns from \l{run()}). This function - will return TRUE if the thread has finished. It also returns - TRUE if the thread has not been started yet. - \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the - default), then the wait will never timeout (the thread must - return from \l{run()}). This function will return FALSE if the - wait timed out. - \endlist - - This provides similar functionality to the POSIX \c pthread_join() function. -*/ -bool TQThread::wait( unsigned long time ) -{ - TQMutexLocker locker( d->mutex() ); - - if ( pthread_equal( d->thread_id, pthread_self() ) ) { -#ifdef QT_CHECK_STATE - tqWarning( "TQThread::wait: thread tried to wait on itself" ); -#endif // QT_CHECK_STATE - - return FALSE; - } - - if ( d->finished || ! d->running ) { - return TRUE; - } - - int ret; - if (time != ULONG_MAX) { - struct timeval tv; - gettimeofday(&tv, 0); - - timespec ti; - ti.tv_nsec = (tv.tv_usec + (time % 1000) * 1000) * 1000; - ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000); - ti.tv_nsec %= 1000000000; - - ret = pthread_cond_timedwait(&d->thread_done, &locker.mutex()->d->handle, &ti); - } - else { - ret = pthread_cond_wait(&d->thread_done, &locker.mutex()->d->handle); - } - -#ifdef QT_CHECK_RANGE - if (ret && ret != ETIMEDOUT) { - tqWarning("Wait condition wait failure: %s",strerror(ret)); - } -#endif - - return (ret == 0); -} - -/*! - Returns the current cleanup behaviour of the thread. - - \sa setCleanupType - \sa CleanupType -*/ - -TQThread::CleanupType TQThread::cleanupType() const { - return (TQThread::CleanupType)d->cleanupType; -} - -/*! - Sets the current cleanup behaviour of the thread. The default, - TQThread::CleanupMergeObjects, will merge any objects owned by this thread - with the main GUI thread when this thread is terminated. - - If faster thread termination performance is desired, TQThread::CleanupNone - may be specified instead. However, this is not recommended as any objects - owned by this thread on termination can then cause events to become "stuck" - in the global event queue, leading to high CPU usage and other undesirable - behavior. You have been warned! - - \sa cleanupType - \sa CleanupType -*/ - -void TQThread::setCleanupType(CleanupType type) { - d->cleanupType = type; -} - -/*! - Returns a pointer to the currently executing TQThread. If the - current thread was not started using the TQThread API, this - function returns zero. - - Note that TQApplication creates a TQThread object to represent the - main thread; calling this function from main() after creating - TQApplication will return a valid pointer. -*/ -TQThread *TQThread::currentThreadObject() -{ - pthread_once(&storage_key_once, create_storage_key); - return reinterpret_cast(pthread_getspecific(storage_key)); -} - - -#endif // TQT_THREAD_SUPPORT diff --git a/src/kernel/tqobject.cpp b/src/kernel/tqobject.cpp index d50b48e85..3923b46d0 100644 --- a/src/kernel/tqobject.cpp +++ b/src/kernel/tqobject.cpp @@ -53,9 +53,9 @@ #include "tqstyle.h" #ifdef TQT_THREAD_SUPPORT -#include "ntqmutex.h" -#include -#include "ntqthread.h" +#include "tqmutex.h" +#include +#include "tqthread.h" #endif #include diff --git a/src/kernel/tqobject.h b/src/kernel/tqobject.h index 2d72bfa25..cc67ba551 100644 --- a/src/kernel/tqobject.h +++ b/src/kernel/tqobject.h @@ -46,7 +46,7 @@ #include "ntqwindowdefs.h" #include "tqstring.h" #include "ntqevent.h" -#include "ntqmutex.h" +#include "tqmutex.h" #include "ntqnamespace.h" #endif // QT_H diff --git a/src/kernel/tqthread.cpp b/src/kernel/tqthread.cpp new file mode 100644 index 000000000..27b2071ea --- /dev/null +++ b/src/kernel/tqthread.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Cross-platform TQThread implementation. +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifdef TQT_THREAD_SUPPORT + +#include "qplatformdefs.h" + +#include "tqthread.h" +#include "ntqeventloop.h" +#include + +#ifndef QT_H +# include "ntqapplication.h" +#endif // QT_H + + +/*! + \class TQThread tqthread.h + \threadsafe + \brief The TQThread class provides platform-independent threads. + + \ingroup thread + \ingroup environment + + A TQThread represents a separate thread of control within the + program; it shares data with all the other threads within the + process but executes independently in the way that a separate + program does on a multitasking operating system. Instead of + starting in main(), TQThreads begin executing in run(). You inherit + run() to include your code. For example: + + \code + class MyThread : public TQThread { + + public: + + virtual void run(); + + }; + + void MyThread::run() + { + for( int count = 0; count < 20; count++ ) { + sleep( 1 ); + tqDebug( "Ping!" ); + } + } + + int main() + { + MyThread a; + MyThread b; + a.start(); + b.start(); + a.wait(); + b.wait(); + } + \endcode + + This will start two threads, each of which writes Ping! 20 times + to the screen and exits. The wait() calls at the end of main() are + necessary because exiting main() ends the program, unceremoniously + killing all other threads. Each MyThread stops executing when it + reaches the end of MyThread::run(), just as an application does + when it leaves main(). + + \sa \link threads.html Thread Support in TQt\endlink. +*/ + +/*! + \enum TQThread::Priority + + This enum type indicates how the operating system should schedule + newly created threads. + + \value IdlePriority scheduled only when no other threads are + running. + + \value LowestPriority scheduled less often than LowPriority. + \value LowPriority scheduled less often than NormalPriority. + + \value NormalPriority the default priority of the operating + system. + + \value HighPriority scheduled more often than NormalPriority. + \value HighestPriority scheduled more often then HighPriority. + + \value TimeCriticalPriority scheduled as often as possible. + + \value InheritPriority use the same priority as the creating + thread. This is the default. +*/ + +TQThread::TQThread() +{ +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( TQApplication::tqt_mutex ); +#endif // TQT_THREAD_SUPPORT + + d = new TQThreadInstance; + d->init(0); +} + +/*! + Constructs a new thread. The thread does not begin executing until + start() is called. + + If \a stackSize is greater than zero, the maximum stack size is + set to \a stackSize bytes, otherwise the maximum stack size is + automatically determined by the operating system. + + \warning Most operating systems place minimum and maximum limits + on thread stack sizes. The thread will fail to start if the stack + size is outside these limits. +*/ +TQThread::TQThread( unsigned int stackSize ) +{ + d = new TQThreadInstance; + d->init(stackSize); +} + +/*! + TQThread destructor. + + Note that deleting a TQThread object will not stop the execution of + the thread it represents. Deleting a running TQThread (i.e. + finished() returns FALSE) will probably result in a program crash. + You can wait() on a thread to make sure that it has finished. +*/ +TQThread::~TQThread() +{ + TQMutexLocker locker( d->mutex() ); + if ( d->running && !d->finished ) { +#ifdef QT_CHECK_STATE + tqWarning("TQThread object destroyed while thread is still running."); +#endif + + d->orphan = TRUE; + return; + } + + d->deinit(); + delete d; +} + +/*! + This function terminates the execution of the thread. The thread + may or may not be terminated immediately, depending on the + operating system's scheduling policies. Use TQThread::wait() + after terminate() for synchronous termination. + + When the thread is terminated, all threads waiting for the + the thread to finish will be woken up. + + \warning This function is dangerous, and its use is discouraged. + The thread can be terminated at any point in its code path. Threads + can be terminated while modifying data. There is no chance for + the thread to cleanup after itself, unlock any held mutexes, etc. + In short, use this function only if \e absolutely necessary. +*/ +void TQThread::terminate() +{ + TQMutexLocker locker( d->mutex() ); + if ( d->finished || !d->running ) + return; + d->terminate(); +} + +/*! + Returns TRUE if the thread is finished; otherwise returns FALSE. +*/ +bool TQThread::finished() const +{ + TQMutexLocker locker( d->mutex() ); + return d->finished; +} + +/*! + Returns TRUE if the thread is running; otherwise returns FALSE. +*/ +bool TQThread::running() const +{ + TQMutexLocker locker( d->mutex() ); + return d->running; +} + +/*! + Changes the way cross thread signals are handled + If disable is FALSE, signals emitted from this thread will be + posted to any other connected threads' event loops (default). + + If disable is TRUE, calls to emit from this thread + will immediately execute slots in another thread. + This mode of operation is inherently unsafe and is provided + solely to support thread management by a third party application. + */ +void TQThread::setThreadPostedEventsDisabled(bool disable) +{ + d->disableThreadPostedEvents = disable; +} + +/*! + Returns TRUE if thread posted events are disabled, FALSE if not + */ +bool TQThread::threadPostedEventsDisabled() const +{ + return d->disableThreadPostedEvents; +} + +/*! + \fn void TQThread::run() + + This method is pure virtual, and must be implemented in derived + classes in order to do useful work. Returning from this method + will end the execution of the thread. + + \sa wait() +*/ + +TQEventLoopThread::TQEventLoopThread() : TQThread() +{ + // +} + +TQEventLoopThread::~TQEventLoopThread() +{ + // +} + +void TQEventLoopThread::run() +{ + TQEventLoop* eventLoop = TQApplication::eventLoop(); + if (eventLoop) eventLoop->exec(); +} + +#endif // TQT_THREAD_SUPPORT diff --git a/src/kernel/tqthread.h b/src/kernel/tqthread.h new file mode 100644 index 000000000..0b38e5a33 --- /dev/null +++ b/src/kernel/tqthread.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Definition of TQThread class +** +** Created : 931107 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQTHREAD_H +#define TQTHREAD_H + +#if defined(TQT_THREAD_SUPPORT) + +#ifndef QT_H +#include "ntqwindowdefs.h" +#endif // QT_H + +#include + +class TQThreadInstance; + +class TQ_EXPORT TQThread : public TQt +{ +public: + static TQt::HANDLE currentThread(); + + static void initialize(); + static void cleanup(); + + static void exit(); + +#ifdef Q_QDOC + TQThread( unsigned int stackSize = 0 ); +#else + TQThread( unsigned int stackSize ); + TQThread(); +#endif + + virtual ~TQThread(); + + // default argument causes thread to block indefinately + bool wait( unsigned long time = ULONG_MAX ); + + enum Priority { + IdlePriority, + + LowestPriority, + LowPriority, + NormalPriority, + HighPriority, + HighestPriority, + + TimeCriticalPriority, + + InheritPriority + }; + +#ifdef Q_QDOC + void start( Priority = InheritPriority ); +#else + void start( Priority ); + void start(); +#endif + + void terminate(); + + bool finished() const; + bool running() const; + + enum CleanupType { + CleanupNone, + CleanupMergeObjects + }; + + CleanupType cleanupType() const; + void setCleanupType(CleanupType); + + bool threadPostedEventsDisabled() const; + void setThreadPostedEventsDisabled(bool); + +protected: + virtual void run() = 0; + + static void sleep( unsigned long ); + static void msleep( unsigned long ); + static void usleep( unsigned long ); + +private: + TQThreadInstance * d; + friend class TQThreadInstance; + friend class TQThreadStorageData; + friend class TQCoreApplicationThread; + friend class TQApplication; + friend class TQEventLoop; + +#if defined(TQ_DISABLE_COPY) + TQThread( const TQThread & ); + TQThread &operator=( const TQThread & ); +#endif // TQ_DISABLE_COPY + +public: + static TQThread* currentThreadObject(); +}; + +class TQ_EXPORT TQEventLoopThread : public TQThread +{ + public: + TQEventLoopThread(); + ~TQEventLoopThread(); + virtual void run(); +}; + +#endif // TQT_THREAD_SUPPORT + +#endif // TQTHREAD_H diff --git a/src/kernel/tqthread_unix.cpp b/src/kernel/tqthread_unix.cpp new file mode 100644 index 000000000..c6662dbeb --- /dev/null +++ b/src/kernel/tqthread_unix.cpp @@ -0,0 +1,569 @@ +/**************************************************************************** +** +** TQThread class for Unix +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#if defined(TQT_THREAD_SUPPORT) + +#include "qplatformdefs.h" + +typedef pthread_mutex_t Q_MUTEX_T; + +#include "tqthread.h" +#include +#include +#include +#include +#include + +#include +#include + +#if defined(QT_USE_GLIBMAINLOOP) +#include +#endif // QT_USE_GLIBMAINLOOP + +static TQMutexPool *qt_thread_mutexpool = 0; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +typedef void*(*TQtThreadCallback)(void*); + +static pthread_once_t storage_key_once = PTHREAD_ONCE_INIT; +static pthread_key_t storage_key; +static void create_storage_key() +{ + pthread_key_create( &storage_key, NULL ); +} + +#if defined(Q_C_CALLBACKS) +} +#endif + + +/************************************************************************** + ** TQThreadInstance + *************************************************************************/ + +void TQThreadInstance::setCurrentThread(TQThread *thread) +{ + pthread_once(&storage_key_once, create_storage_key); + pthread_setspecific(storage_key, thread); +} + +TQThreadInstance *TQThreadInstance::current() +{ + TQThreadInstance *ret = NULL; + pthread_once( &storage_key_once, create_storage_key ); + TQThread *thread = (TQThread *) pthread_getspecific( storage_key ); + if (thread) { + ret = thread->d; + } + return ret; +} + +void TQThreadInstance::init(unsigned int stackSize) +{ + stacksize = stackSize; + args[0] = args[1] = 0; + thread_storage = 0; + finished = FALSE; + running = FALSE; + orphan = FALSE; + disableThreadPostedEvents = FALSE; + + pthread_cond_init(&thread_done, NULL); + thread_id = 0; + + eventLoop = 0; + cleanupType = TQThread::CleanupMergeObjects; + + // threads have not been initialized yet, do it now + if (! qt_thread_mutexpool) TQThread::initialize(); +} + +void TQThreadInstance::deinit() +{ + pthread_cond_destroy(&thread_done); +} + +void *TQThreadInstance::start( void *_arg ) +{ + void **arg = (void **) _arg; + +#if defined(QT_USE_GLIBMAINLOOP) + // This is the first time we have access to the native pthread ID of this newly created thread + ((TQThreadInstance*)arg[1])->thread_id = pthread_self(); +#endif // QT_USE_GLIBMAINLOOP + +#ifdef QT_DEBUG + tqDebug("TQThreadInstance::start: Setting thread storage to %p\n", (TQThread *) arg[0]); +#endif // QT_DEBUG + setCurrentThread( (TQThread *) arg[0] ); + + pthread_cleanup_push( TQThreadInstance::finish, arg[1] ); + pthread_testcancel(); + + ( (TQThread *) arg[0] )->run(); + + pthread_cleanup_pop( TRUE ); + return 0; +} + +void TQThreadInstance::finish( void * ) +{ + TQThreadInstance *d = current(); + + if ( ! d ) { +#ifdef QT_CHECK_STATE + tqWarning( "TQThread: internal error: zero data for running thread." ); +#endif // QT_CHECK_STATE + return; + } + +#ifdef QT_DEBUG + tqDebug("TQThreadInstance::finish: In TQThreadInstance::finish for thread %p\n", (TQThread*)d->args[0]); +#endif // QT_DEBUG + + TQApplication::threadTerminationHandler((TQThread*)d->args[0]); + + TQMutexLocker locker( d->mutex() ); + d->running = FALSE; + d->finished = TRUE; + d->args[0] = d->args[1] = 0; + + + TQThreadStorageData::finish( d->thread_storage ); + d->thread_storage = 0; + + d->thread_id = 0; + pthread_cond_broadcast(&d->thread_done); + + if (d->orphan) { + d->deinit(); + delete d; + } +} + +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; +} + +void TQThreadInstance::terminate() +{ + if ( ! thread_id ) return; + pthread_cancel( thread_id ); +} + +/************************************************************************** + ** TQThread + *************************************************************************/ + +/*! + This returns the thread handle of the currently executing thread. + + \warning The handle returned by this function is used for internal + purposes and should \e not be used in any application code. On + Windows, the returned value is a pseudo handle for the current + thread, and it cannot be used for numerical comparison. +*/ +TQt::HANDLE TQThread::currentThread() +{ + return (HANDLE) pthread_self(); +} + +/*! \internal + Initializes the TQThread system. +*/ +void TQThread::initialize() +{ + if ( ! tqt_global_mutexpool ) + tqt_global_mutexpool = new TQMutexPool( TRUE, 73 ); + if ( ! qt_thread_mutexpool ) + qt_thread_mutexpool = new TQMutexPool( FALSE, 127 ); +} + +/*! \internal + Cleans up the TQThread system. +*/ +void TQThread::cleanup() +{ + delete tqt_global_mutexpool; + delete qt_thread_mutexpool; + tqt_global_mutexpool = 0; + qt_thread_mutexpool = 0; +} + +/*! + Ends the execution of the calling thread and wakes up any threads + waiting for its termination. +*/ +void TQThread::exit() +{ + pthread_exit( 0 ); +} + +/* \internal + helper function to do thread sleeps, since usleep()/nanosleep() + aren't reliable enough (in terms of behavior and availability) +*/ +static void thread_sleep( struct timespec *ti ) +{ + pthread_mutex_t mtx; + pthread_cond_t cnd; + + pthread_mutex_init(&mtx, 0); + pthread_cond_init(&cnd, 0); + + pthread_mutex_lock( &mtx ); + (void) pthread_cond_timedwait( &cnd, &mtx, ti ); + pthread_mutex_unlock( &mtx ); + + pthread_cond_destroy( &cnd ); + pthread_mutex_destroy( &mtx ); +} + +/*! + System independent sleep. This causes the current thread to sleep + for \a secs seconds. +*/ +void TQThread::sleep( unsigned long secs ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + struct timespec ti; + ti.tv_sec = tv.tv_sec + secs; + ti.tv_nsec = ( tv.tv_usec * 1000 ); + thread_sleep( &ti ); +} + +/*! + System independent sleep. This causes the current thread to sleep + for \a msecs milliseconds +*/ +void TQThread::msleep( unsigned long msecs ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + struct timespec ti; + + ti.tv_nsec = ( tv.tv_usec + ( msecs % 1000 ) * 1000 ) * 1000; + ti.tv_sec = tv.tv_sec + ( msecs / 1000 ) + ( ti.tv_nsec / 1000000000 ); + ti.tv_nsec %= 1000000000; + thread_sleep( &ti ); +} + +/*! + System independent sleep. This causes the current thread to sleep + for \a usecs microseconds +*/ +void TQThread::usleep( unsigned long usecs ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + struct timespec ti; + + ti.tv_nsec = ( tv.tv_usec + ( usecs % 1000000 ) ) * 1000; + ti.tv_sec = tv.tv_sec + ( usecs / 1000000 ) + ( ti.tv_nsec / 1000000000 ); + ti.tv_nsec %= 1000000000; + thread_sleep( &ti ); +} + +/*! + Begins execution of the thread by calling run(), which should be + reimplemented in a TQThread subclass to contain your code. The + operating system will schedule the thread according to the \a + priority argument. + + If you try to start a thread that is already running, this + function will wait until the the thread has finished and then + restart the thread. + + \sa Priority +*/ +void TQThread::start(Priority priority) +{ + TQMutexLocker locker( d->mutex() ); + + if ( d->running ) + pthread_cond_wait(&d->thread_done, &locker.mutex()->d->handle); + d->running = TRUE; + d->finished = FALSE; + + int ret; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0) +#if _POSIX_THREAD_PRIORITY_SCHEDULING == 0 && defined _SC_THREAD_PRIORITY_SCHEDULING + if (sysconf(_SC_THREAD_PRIORITY_SCHEDULING) > 0) +#endif + switch (priority) { + case InheritPriority: + { + pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); + break; + } + + default: + { + int sched_policy; + if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) { + // failed to get the scheduling policy, don't bother + // setting the priority + tqWarning("TQThread: cannot determine default scheduler policy"); + break; + } + + int prio_min = sched_get_priority_min(sched_policy); + int prio_max = sched_get_priority_max(sched_policy); + if (prio_min == -1 || prio_max == -1) { + // failed to get the scheduling parameters, don't + // bother setting the priority + tqWarning("TQThread: cannot determine scheduler priority range"); + break; + } + + int prio; + switch (priority) { + case IdlePriority: + prio = prio_min; + break; + + case HighestPriority: + prio = prio_max; + break; + + default: + // crudely scale our priority enum values to the prio_min/prio_max + prio = (((prio_max - prio_min) / TimeCriticalPriority) * + priority) + prio_min; + prio = TQMAX(prio_min, TQMIN(prio_max, prio)); + break; + } + + sched_param sp; + sp.sched_priority = prio; + + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedparam(&attr, &sp); + break; + } + } +#endif // _POSIX_THREAD_PRIORITY_SCHEDULING + + if ( d->stacksize > 0 ) { +#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0) + ret = pthread_attr_setstacksize( &attr, d->stacksize ); +#else + ret = ENOSYS; // stack size not supported, automatically fail +#endif // _POSIX_THREAD_ATTR_STACKSIZE + + if ( ret ) { +#ifdef QT_CHECK_STATE + tqWarning( "TQThread::start: thread stack size error: %s", strerror( ret ) ) ; +#endif // QT_CHECK_STATE + + // we failed to set the stacksize, and as the documentation states, + // the thread will fail to run... + d->running = FALSE; + d->finished = FALSE; + return; + } + } + + d->args[0] = this; + d->args[1] = d; +#if defined(QT_USE_GLIBMAINLOOP) + // The correct thread_id is set in TQThreadInstance::start using the value of d->args[1] + d->thread_id = 0; + + // glib versions < 2.32.0 requires threading system initialization call + #if GLIB_CHECK_VERSION(2, 32, 0) + GThread* glib_thread_handle = g_thread_new( NULL, (GThreadFunc)TQThreadInstance::start, d->args ); + #else + if( !g_thread_get_initialized() ); + g_thread_init(NULL); + GThread* glib_thread_handle = g_thread_create((GThreadFunc)TQThreadInstance::start, d->args, false, NULL); + #endif + + if (glib_thread_handle) { + ret = 0; + } + else { + ret = -1; + } +#else // QT_USE_GLIBMAINLOOP + ret = pthread_create( &d->thread_id, &attr, (TQtThreadCallback)TQThreadInstance::start, d->args ); +#if defined (Q_OS_HPUX) + if (ret == EPERM) { + pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); + ret = pthread_create(&d->thread_id, &attr, (TQtThreadCallback)TQThreadInstance::start, d->args); + } +#endif + pthread_attr_destroy( &attr ); +#endif // QT_USE_GLIBMAINLOOP + + if ( ret ) { +#ifdef QT_CHECK_STATE + tqWarning( "TQThread::start: thread creation error: %s", strerror( ret ) ); +#endif // QT_CHECK_STATE + + d->running = FALSE; + d->finished = FALSE; + d->args[0] = d->args[1] = 0; + } +} + +void TQThread::start() +{ + start(InheritPriority); +} + +/*! + A thread calling this function will block until either of these + conditions is met: + + \list + \i The thread associated with this TQThread object has finished + execution (i.e. when it returns from \l{run()}). This function + will return TRUE if the thread has finished. It also returns + TRUE if the thread has not been started yet. + \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + default), then the wait will never timeout (the thread must + return from \l{run()}). This function will return FALSE if the + wait timed out. + \endlist + + This provides similar functionality to the POSIX \c pthread_join() function. +*/ +bool TQThread::wait( unsigned long time ) +{ + TQMutexLocker locker( d->mutex() ); + + if ( pthread_equal( d->thread_id, pthread_self() ) ) { +#ifdef QT_CHECK_STATE + tqWarning( "TQThread::wait: thread tried to wait on itself" ); +#endif // QT_CHECK_STATE + + return FALSE; + } + + if ( d->finished || ! d->running ) { + return TRUE; + } + + int ret; + if (time != ULONG_MAX) { + struct timeval tv; + gettimeofday(&tv, 0); + + timespec ti; + ti.tv_nsec = (tv.tv_usec + (time % 1000) * 1000) * 1000; + ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec %= 1000000000; + + ret = pthread_cond_timedwait(&d->thread_done, &locker.mutex()->d->handle, &ti); + } + else { + ret = pthread_cond_wait(&d->thread_done, &locker.mutex()->d->handle); + } + +#ifdef QT_CHECK_RANGE + if (ret && ret != ETIMEDOUT) { + tqWarning("Wait condition wait failure: %s",strerror(ret)); + } +#endif + + return (ret == 0); +} + +/*! + Returns the current cleanup behaviour of the thread. + + \sa setCleanupType + \sa CleanupType +*/ + +TQThread::CleanupType TQThread::cleanupType() const { + return (TQThread::CleanupType)d->cleanupType; +} + +/*! + Sets the current cleanup behaviour of the thread. The default, + TQThread::CleanupMergeObjects, will merge any objects owned by this thread + with the main GUI thread when this thread is terminated. + + If faster thread termination performance is desired, TQThread::CleanupNone + may be specified instead. However, this is not recommended as any objects + owned by this thread on termination can then cause events to become "stuck" + in the global event queue, leading to high CPU usage and other undesirable + behavior. You have been warned! + + \sa cleanupType + \sa CleanupType +*/ + +void TQThread::setCleanupType(CleanupType type) { + d->cleanupType = type; +} + +/*! + Returns a pointer to the currently executing TQThread. If the + current thread was not started using the TQThread API, this + function returns zero. + + Note that TQApplication creates a TQThread object to represent the + main thread; calling this function from main() after creating + TQApplication will return a valid pointer. +*/ +TQThread *TQThread::currentThreadObject() +{ + pthread_once(&storage_key_once, create_storage_key); + return reinterpret_cast(pthread_getspecific(storage_key)); +} + + +#endif // TQT_THREAD_SUPPORT diff --git a/src/kernel/tqwidget.cpp b/src/kernel/tqwidget.cpp index 8dfda823c..d5419c8d0 100644 --- a/src/kernel/tqwidget.cpp +++ b/src/kernel/tqwidget.cpp @@ -57,7 +57,7 @@ #include "ntqmetaobject.h" #include "ntqguardedptr.h" #if defined(TQT_THREAD_SUPPORT) -#include "ntqthread.h" +#include "tqthread.h" #endif #if defined(QT_ACCESSIBILITY_SUPPORT) #include "ntqaccessible.h" -- cgit v1.2.3