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/codecs/tqtextcodec.cpp | 2 +- src/codecs/tqtextcodecfactory.cpp | 2 +- src/dialogs/qfiledialog.cpp | 2 +- src/inputmethod/qinputcontextfactory.cpp | 2 +- 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 +- src/styles/qcommonstyle.cpp | 2 +- src/tools/ntqmutex.h | 117 ------- src/tools/ntqsemaphore.h | 81 ----- src/tools/ntqthreadstorage.h | 95 ------ src/tools/ntqwaitcondition.h | 79 ----- src/tools/qcomlibrary.cpp | 2 +- src/tools/qcstring.cpp | 2 +- src/tools/qdir_unix.cpp | 2 +- src/tools/qgarray.cpp | 2 +- src/tools/qglist.cpp | 2 +- src/tools/qgvector.cpp | 2 +- src/tools/qlocale.cpp | 4 +- src/tools/qmutex_p.h | 74 ---- src/tools/qmutex_unix.cpp | 535 ----------------------------- src/tools/qmutexpool.cpp | 155 --------- src/tools/qmutexpool_p.h | 80 ----- src/tools/qregexp.cpp | 4 +- src/tools/qsemaphore.cpp | 255 -------------- src/tools/qt_tools.pri | 30 +- src/tools/qthreadinstance_p.h | 111 ------ src/tools/qthreadstorage_unix.cpp | 366 -------------------- src/tools/qwaitcondition_unix.cpp | 316 ----------------- src/tools/tqmutex.h | 117 +++++++ src/tools/tqmutex_p.h | 74 ++++ src/tools/tqmutex_unix.cpp | 535 +++++++++++++++++++++++++++++ src/tools/tqmutexpool.cpp | 155 +++++++++ src/tools/tqmutexpool_p.h | 80 +++++ src/tools/tqsemaphore.cpp | 255 ++++++++++++++ src/tools/tqsemaphore.h | 81 +++++ src/tools/tqstring.cpp | 2 +- src/tools/tqthreadinstance_p.h | 111 ++++++ src/tools/tqthreadstorage.h | 95 ++++++ src/tools/tqthreadstorage_unix.cpp | 366 ++++++++++++++++++++ src/tools/tqwaitcondition.h | 79 +++++ src/tools/tqwaitcondition_unix.cpp | 316 +++++++++++++++++ 58 files changed, 3308 insertions(+), 3308 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 delete mode 100644 src/tools/ntqmutex.h delete mode 100644 src/tools/ntqsemaphore.h delete mode 100644 src/tools/ntqthreadstorage.h delete mode 100644 src/tools/ntqwaitcondition.h delete mode 100644 src/tools/qmutex_p.h delete mode 100644 src/tools/qmutex_unix.cpp delete mode 100644 src/tools/qmutexpool.cpp delete mode 100644 src/tools/qmutexpool_p.h delete mode 100644 src/tools/qsemaphore.cpp delete mode 100644 src/tools/qthreadinstance_p.h delete mode 100644 src/tools/qthreadstorage_unix.cpp delete mode 100644 src/tools/qwaitcondition_unix.cpp create mode 100644 src/tools/tqmutex.h create mode 100644 src/tools/tqmutex_p.h create mode 100644 src/tools/tqmutex_unix.cpp create mode 100644 src/tools/tqmutexpool.cpp create mode 100644 src/tools/tqmutexpool_p.h create mode 100644 src/tools/tqsemaphore.cpp create mode 100644 src/tools/tqsemaphore.h create mode 100644 src/tools/tqthreadinstance_p.h create mode 100644 src/tools/tqthreadstorage.h create mode 100644 src/tools/tqthreadstorage_unix.cpp create mode 100644 src/tools/tqwaitcondition.h create mode 100644 src/tools/tqwaitcondition_unix.cpp (limited to 'src') diff --git a/src/codecs/tqtextcodec.cpp b/src/codecs/tqtextcodec.cpp index 0609ae294..8d2c0bb17 100644 --- a/src/codecs/tqtextcodec.cpp +++ b/src/codecs/tqtextcodec.cpp @@ -76,7 +76,7 @@ #endif #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #include diff --git a/src/codecs/tqtextcodecfactory.cpp b/src/codecs/tqtextcodecfactory.cpp index 24ac82a09..b98155587 100644 --- a/src/codecs/tqtextcodecfactory.cpp +++ b/src/codecs/tqtextcodecfactory.cpp @@ -49,7 +49,7 @@ #include "tqtextcodecinterface_p.h" #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #include diff --git a/src/dialogs/qfiledialog.cpp b/src/dialogs/qfiledialog.cpp index 7dfc1fb2a..983c817d3 100644 --- a/src/dialogs/qfiledialog.cpp +++ b/src/dialogs/qfiledialog.cpp @@ -100,7 +100,7 @@ #ifdef TQ_WS_WIN #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #endif // TQ_WS_WIN diff --git a/src/inputmethod/qinputcontextfactory.cpp b/src/inputmethod/qinputcontextfactory.cpp index a54d2d24c..9199f8088 100644 --- a/src/inputmethod/qinputcontextfactory.cpp +++ b/src/inputmethod/qinputcontextfactory.cpp @@ -44,7 +44,7 @@ #include "ntqapplication.h" #ifdef TQT_THREAD_SUPPORT -#include +#include #endif // TQT_THREAD_SUPPORT #include 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" diff --git a/src/styles/qcommonstyle.cpp b/src/styles/qcommonstyle.cpp index 3ce552ebd..9f1610620 100644 --- a/src/styles/qcommonstyle.cpp +++ b/src/styles/qcommonstyle.cpp @@ -42,7 +42,7 @@ #ifndef TQT_NO_STYLE -#include "ntqmutex.h" +#include "tqmutex.h" #include "ntqmenubar.h" #include "ntqapplication.h" #include "ntqpainter.h" diff --git a/src/tools/ntqmutex.h b/src/tools/ntqmutex.h deleted file mode 100644 index c517c6355..000000000 --- a/src/tools/ntqmutex.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Definition of TQMutex class -** -** Created : 931107 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQMUTEX_H -#define TQMUTEX_H - -#ifndef QT_H -#include "ntqglobal.h" -#endif // QT_H - -#if defined(TQT_THREAD_SUPPORT) - -class TQMutexPrivate; - -const int Q_MUTEX_NORMAL = 0; -const int Q_MUTEX_RECURSIVE = 1; - -class TQ_EXPORT TQMutex -{ - friend class TQThread; - friend class TQWaitCondition; - friend class TQWaitConditionPrivate; - -public: - TQMutex(bool recursive = FALSE); - virtual ~TQMutex(); - - void lock(); - void unlock(); - bool locked(); - bool tryLock(); - -private: - TQMutexPrivate * d; - -#if defined(TQ_DISABLE_COPY) - TQMutex( const TQMutex & ); - TQMutex &operator=( const TQMutex & ); -#endif - -public: - int level(); -}; - -class TQ_EXPORT TQMutexLocker -{ -public: - TQMutexLocker( TQMutex * ); - ~TQMutexLocker(); - - TQMutex *mutex() const; - -private: - TQMutex *mtx; - -#if defined(TQ_DISABLE_COPY) - TQMutexLocker( const TQMutexLocker & ); - TQMutexLocker &operator=( const TQMutexLocker & ); -#endif -}; - -inline TQMutexLocker::TQMutexLocker( TQMutex *m ) - : mtx( m ) -{ - if ( mtx ) mtx->lock(); -} - -inline TQMutexLocker::~TQMutexLocker() -{ - if ( mtx ) mtx->unlock(); -} - -inline TQMutex *TQMutexLocker::mutex() const -{ - return mtx; -} - -#endif - -#endif diff --git a/src/tools/ntqsemaphore.h b/src/tools/ntqsemaphore.h deleted file mode 100644 index 0dc8e81de..000000000 --- a/src/tools/ntqsemaphore.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Definition of TQSemaphore class -** -** Created : 931107 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQSEMAPHORE_H -#define TQSEMAPHORE_H - -#ifndef QT_H -#include "ntqglobal.h" -#endif // QT_H - -#if defined(TQT_THREAD_SUPPORT) - -class TQSemaphorePrivate; - -class TQ_EXPORT TQSemaphore -{ -public: - TQSemaphore( int ); - virtual ~TQSemaphore(); - - int available() const; - int total() const; - - // postfix operators - int operator++(int); - int operator--(int); - - int operator+=(int); - int operator-=(int); - - bool tryAccess(int); - -private: - TQSemaphorePrivate *d; - -#if defined(TQ_DISABLE_COPY) - TQSemaphore(const TQSemaphore &); - TQSemaphore &operator=(const TQSemaphore &); -#endif -}; - -#endif - -#endif diff --git a/src/tools/ntqthreadstorage.h b/src/tools/ntqthreadstorage.h deleted file mode 100644 index 588621237..000000000 --- a/src/tools/ntqthreadstorage.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQTHREADSTORAGE_H -#define TQTHREADSTORAGE_H - -#ifdef TQT_THREAD_SUPPORT - -#ifndef QT_H -#include "ntqglobal.h" -#endif // QT_H - -class TQ_EXPORT TQThreadStorageData -{ -public: - TQThreadStorageData( void (*func)(void *) ); - ~TQThreadStorageData(); - - void** get() const; - void** set( void* p ); - - static void finish( void** ); - int id; -}; - - -template -class TQThreadStorage -{ -private: - TQThreadStorageData d; - -#if defined(TQ_DISABLE_COPY) - // disable copy constructor and operator= - TQThreadStorage( const TQThreadStorage & ); - TQThreadStorage &operator=( const TQThreadStorage & ); -#endif // TQ_DISABLE_COPY - - static void deleteData( void *x ) { delete (T)x; } - -public: - inline TQThreadStorage() : d( deleteData ) { } - inline ~TQThreadStorage() { } - - inline bool hasLocalData() const - { return d.get() != 0; } - - inline T& localData() - { void **v = d.get(); if ( !v ) v = d.set( 0 ); return *(T*)v; } - - inline T localData() const - { void **v = d.get(); return ( v ? *(T*)v : 0 ); } - - inline void setLocalData( T t ) - { (void) d.set( t ); } -}; - -#endif // TQT_THREAD_SUPPORT - -#endif // TQTHREADSTORAGE_H diff --git a/src/tools/ntqwaitcondition.h b/src/tools/ntqwaitcondition.h deleted file mode 100644 index 503d5d6c9..000000000 --- a/src/tools/ntqwaitcondition.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Definition of TQWaitCondition class -** -** Created : 931107 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQWAITCONDITION_H -#define TQWAITCONDITION_H - -#ifndef QT_H -#include "ntqglobal.h" -#endif // QT_H - -#if defined(TQT_THREAD_SUPPORT) - -#include - -class TQWaitConditionPrivate; -class TQMutex; - -class TQ_EXPORT TQWaitCondition -{ -public: - TQWaitCondition(); - virtual ~TQWaitCondition(); - - // default argument causes thread to block indefinately - bool wait( unsigned long time = ULONG_MAX ); - bool wait( TQMutex *mutex, unsigned long time = ULONG_MAX ); - - void wakeOne(); - void wakeAll(); - -private: - TQWaitConditionPrivate * d; - -#if defined(TQ_DISABLE_COPY) - TQWaitCondition( const TQWaitCondition & ); - TQWaitCondition &operator=( const TQWaitCondition & ); -#endif -}; - -#endif - -#endif diff --git a/src/tools/qcomlibrary.cpp b/src/tools/qcomlibrary.cpp index 27ffbb8ce..cc7647da9 100644 --- a/src/tools/qcomlibrary.cpp +++ b/src/tools/qcomlibrary.cpp @@ -49,7 +49,7 @@ #endif // NO_ERROR_H #ifdef TQT_THREAD_SUPPORT -# include "qmutexpool_p.h" +# include "tqmutexpool_p.h" #endif // TQT_THREAD_SUPPORT #ifndef QT_DEBUG_COMPONENT diff --git a/src/tools/qcstring.cpp b/src/tools/qcstring.cpp index 80381e8b9..d35b06e3e 100644 --- a/src/tools/qcstring.cpp +++ b/src/tools/qcstring.cpp @@ -44,7 +44,7 @@ #include "ntqdatastream.h" #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #include diff --git a/src/tools/qdir_unix.cpp b/src/tools/qdir_unix.cpp index 19e03e642..8019d7b16 100644 --- a/src/tools/qdir_unix.cpp +++ b/src/tools/qdir_unix.cpp @@ -49,7 +49,7 @@ #include "tqstringlist.h" #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #include diff --git a/src/tools/qgarray.cpp b/src/tools/qgarray.cpp index ff1f7b08b..1470d100e 100644 --- a/src/tools/qgarray.cpp +++ b/src/tools/qgarray.cpp @@ -53,7 +53,7 @@ #include #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT /* diff --git a/src/tools/qglist.cpp b/src/tools/qglist.cpp index 1afa67b41..95e66b38f 100644 --- a/src/tools/qglist.cpp +++ b/src/tools/qglist.cpp @@ -44,7 +44,7 @@ #include "tqvaluelist.h" #if defined(TQT_THREAD_SUPPORT) - #include "ntqmutex.h" + #include "tqmutex.h" #endif // defined(TQT_THREAD_SUPPORT) /*! diff --git a/src/tools/qgvector.cpp b/src/tools/qgvector.cpp index 81b7a2006..1c6c8669e 100644 --- a/src/tools/qgvector.cpp +++ b/src/tools/qgvector.cpp @@ -52,7 +52,7 @@ #include #ifdef TQT_THREAD_SUPPORT -# include +# include #endif // TQT_THREAD_SUPPORT #define USE_MALLOC // comment to use new/delete diff --git a/src/tools/qlocale.cpp b/src/tools/qlocale.cpp index d7716a1a7..fc02f8ef2 100644 --- a/src/tools/qlocale.cpp +++ b/src/tools/qlocale.cpp @@ -48,8 +48,8 @@ #include "ntqnamespace.h" #ifdef QT_QLOCALE_USES_FCVT -# include -# include +# include +# include #endif #if defined (Q_OS_WIN) diff --git a/src/tools/qmutex_p.h b/src/tools/qmutex_p.h deleted file mode 100644 index 3e9de8e5c..000000000 --- a/src/tools/qmutex_p.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** TQMutex private class declarations -** -** Created : 20012507 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQMUTEX_P_H -#define TQMUTEX_P_H - -#ifndef QT_H -#endif // QT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of qmutex_unix.cpp and qmutex_win.cpp. This header file may change -// from version to version without notice, or even be removed. -// -// We mean it. -// - -class TQMutexPrivate { -public: - // Q_MUTEX_T is defined in the various *.cpp files - Q_MUTEX_T handle; - - virtual ~TQMutexPrivate(); - - virtual void lock() = 0; - virtual void unlock() = 0; - virtual bool locked() = 0; - virtual bool trylock() = 0; - virtual int type() const = 0; - virtual int level() = 0; -}; - - -#endif // TQMUTEX_P_H diff --git a/src/tools/qmutex_unix.cpp b/src/tools/qmutex_unix.cpp deleted file mode 100644 index 597d3e628..000000000 --- a/src/tools/qmutex_unix.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/**************************************************************************** -** -** TQMutex class for Unix -** -** Created : 20010725 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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; - -#if defined(QT_CHECK_RANGE) -# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK -#else -# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT -#endif -#define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE - -#include "ntqmutex.h" -#include "qmutex_p.h" - -#include -#include - -// Private class declarations - -class TQRealMutexPrivate : public TQMutexPrivate { -public: - TQRealMutexPrivate(bool = FALSE); - - void lock(); - void unlock(); - bool locked(); - bool trylock(); - int type() const; - int level(); - - bool recursive; - int count; -}; - - -// Private class implementation - -// base destructor -TQMutexPrivate::~TQMutexPrivate() -{ - int ret = pthread_mutex_destroy(&handle); - -#ifdef QT_CHECK_RANGE - if ( ret ) - tqWarning( "Mutex destroy failure: %s", strerror( ret ) ); -#endif -} - -// real mutex class -TQRealMutexPrivate::TQRealMutexPrivate(bool recurs) - : recursive(recurs), count(0) -{ - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); - int ret = pthread_mutex_init(&handle, &attr); - pthread_mutexattr_destroy(&attr); - -#ifdef QT_CHECK_RANGE - if( ret ) - tqWarning( "Mutex init failure: %s", strerror( ret ) ); -#endif // QT_CHECK_RANGE -} - -void TQRealMutexPrivate::lock() -{ - int ret = pthread_mutex_lock(&handle); - - if (!ret) { - count++; - } else { -#ifdef QT_CHECK_RANGE - tqWarning("Mutex lock failure: %s", strerror(ret)); -#endif - } -} - -void TQRealMutexPrivate::unlock() -{ - count--; - int ret = pthread_mutex_unlock(&handle); - - if (ret) { - count++; -#ifdef QT_CHECK_RANGE - tqWarning("Mutex unlock failure: %s", strerror(ret)); -#endif - } -} - -bool TQRealMutexPrivate::locked() -{ - return count > 0; -} - -bool TQRealMutexPrivate::trylock() -{ - int ret = pthread_mutex_trylock(&handle); - - if (ret == EBUSY) { - return FALSE; - } else if (ret) { -#ifdef QT_CHECK_RANGE - tqWarning("Mutex trylock failure: %s", strerror(ret)); -#endif - return FALSE; - } - - return TRUE; -} - -int TQRealMutexPrivate::type() const -{ - return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; -} - -int TQRealMutexPrivate::level() -{ - return count; -} - - -/*! - \class TQMutex ntqmutex.h - \threadsafe - \brief The TQMutex class provides access serialization between threads. - - \ingroup thread - \ingroup environment - - The purpose of a TQMutex is to protect an object, data structure or - section of code so that only one thread can access it at a time - (This is similar to the Java \c synchronized keyword). For - example, say there is a method which prints a message to the user - on two lines: - - \code - int number = 6; - - void method1() - { - number *= 5; - number /= 4; - } - - void method2() - { - number *= 3; - number /= 2; - } - \endcode - - If these two methods are called in succession, the following happens: - - \code - // method1() - number *= 5; // number is now 30 - number /= 4; // number is now 7 - - // method2() - number *= 3; // nubmer is now 21 - number /= 2; // number is now 10 - \endcode - - If these two methods are called simultaneously from two threads then the - following sequence could result: - - \code - // Thread 1 calls method1() - number *= 5; // number is now 30 - - // Thread 2 calls method2(). - // - // Most likely Thread 1 has been put to sleep by the operating - // system to allow Thread 2 to run. - number *= 3; // number is now 90 - number /= 2; // number is now 45 - - // Thread 1 finishes executing. - number /= 4; // number is now 11, instead of 10 - \endcode - - If we add a mutex, we should get the result we want: - - \code - TQMutex mutex; - int number = 6; - - void method1() - { - mutex.lock(); - number *= 5; - number /= 4; - mutex.unlock(); - } - - void method2() - { - mutex.lock(); - number *= 3; - number /= 2; - mutex.unlock(); - } - \endcode - - Then only one thread can modify \c number at any given time and - the result is correct. This is a trivial example, of course, but - applies to any other case where things need to happen in a - particular sequence. - - When you call lock() in a thread, other threads that try to call - lock() in the same place will block until the thread that got the - lock calls unlock(). A non-blocking alternative to lock() is - tryLock(). -*/ - -/*! - Constructs a new mutex. The mutex is created in an unlocked state. - A recursive mutex is created if \a recursive is TRUE; a normal - mutex is created if \a recursive is FALSE (the default). With a - recursive mutex, a thread can lock the same mutex multiple times - and it will not be unlocked until a corresponding number of - unlock() calls have been made. -*/ -TQMutex::TQMutex(bool recursive) -{ - d = new TQRealMutexPrivate(recursive); -} - -/*! - Destroys the mutex. - - \warning If you destroy a mutex that still holds a lock the - resultant behavior is undefined. -*/ -TQMutex::~TQMutex() -{ - delete d; -} - -/*! - Attempt to lock the mutex. If another thread has locked the mutex - then this call will \e block until that thread has unlocked it. - - \sa unlock(), locked() -*/ -void TQMutex::lock() -{ - d->lock(); -} - -/*! - Unlocks the mutex. Attempting to unlock a mutex in a different - thread to the one that locked it results in an error. Unlocking a - mutex that is not locked results in undefined behaviour (varies - between different Operating Systems' thread implementations). - - \sa lock(), locked() -*/ -void TQMutex::unlock() -{ - d->unlock(); -} - -/*! - Returns TRUE if the mutex is locked by another thread; otherwise - returns FALSE. - - \warning Due to differing implementations of recursive mutexes on - various platforms, calling this function from the same thread that - previously locked the mutex will return undefined results. - - \sa lock(), unlock() -*/ -bool TQMutex::locked() -{ - return d->locked(); -} - -/*! - Attempt to lock the mutex. If the lock was obtained, this function - returns TRUE. If another thread has locked the mutex, this - function returns FALSE, instead of waiting for the mutex to become - available, i.e. it does not block. - - If the lock was obtained, the mutex must be unlocked with unlock() - before another thread can successfully lock it. - - \sa lock(), unlock(), locked() -*/ -bool TQMutex::tryLock() -{ - return d->trylock(); -} - -/*! - Returns the current lock level of the mutex. - 0 means the mutex is unlocked - This method should only be called when the mutex has already been locked - by lock(), otherwise the lock level could change before the next line - of code is executed. - - WARNING: Non-recursive mutexes will never exceed a lock level of 1! - - \sa lock(), unlock(), locked() -*/ -int TQMutex::level() -{ - return d->level(); -} - -/*! - \class TQMutexLocker ntqmutex.h - \brief The TQMutexLocker class simplifies locking and unlocking TQMutexes. - - \threadsafe - - \ingroup thread - \ingroup environment - - The purpose of TQMutexLocker is to simplify TQMutex locking and - unlocking. Locking and unlocking a TQMutex in complex functions and - statements or in exception handling code is error prone and - difficult to debug. TQMutexLocker should be used in such situations - to ensure that the state of the mutex is well defined and always - locked and unlocked properly. - - TQMutexLocker should be created within a function where a TQMutex - needs to be locked. The mutex is locked when TQMutexLocker is - created, and unlocked when TQMutexLocker is destroyed. - - For example, this complex function locks a TQMutex upon entering - the function and unlocks the mutex at all the exit points: - - \code - int complexFunction( int flag ) - { - mutex.lock(); - - int return_value = 0; - - switch ( flag ) { - case 0: - case 1: - { - mutex.unlock(); - return moreComplexFunction( flag ); - } - - case 2: - { - int status = anotherFunction(); - if ( status < 0 ) { - mutex.unlock(); - return -2; - } - return_value = status + flag; - break; - } - - default: - { - if ( flag > 10 ) { - mutex.unlock(); - return -1; - } - break; - } - } - - mutex.unlock(); - return return_value; - } - \endcode - - This example function will get more complicated as it is - developed, which increases the likelihood that errors will occur. - - Using TQMutexLocker greatly simplifies the code, and makes it more - readable: - - \code - int complexFunction( int flag ) - { - TQMutexLocker locker( &mutex ); - - int return_value = 0; - - switch ( flag ) { - case 0: - case 1: - { - return moreComplexFunction( flag ); - } - - case 2: - { - int status = anotherFunction(); - if ( status < 0 ) - return -2; - return_value = status + flag; - break; - } - - default: - { - if ( flag > 10 ) - return -1; - break; - } - } - - return return_value; - } - \endcode - - Now, the mutex will always be unlocked when the TQMutexLocker - object is destroyed (when the function returns since \c locker is - an auto variable). Note that the mutex will be unlocked after - the call to moreComplexFunction() in this example, avoiding - possible bugs caused by unlocking the mutex too early, as in - the first example. - - The same principle applies to code that throws and catches - exceptions. An exception that is not caught in the function that - has locked the mutex has no way of unlocking the mutex before the - exception is passed up the stack to the calling function. - - TQMutexLocker also provides a mutex() member function that returns - the mutex on which the TQMutexLocker is operating. This is useful - for code that needs access to the mutex, such as - TQWaitCondition::wait(). For example: - - \code - class SignalWaiter - { - private: - TQMutexLocker locker; - - public: - SignalWaiter( TQMutex *mutex ) - : locker( mutex ) - { - } - - void waitForSignal() - { - ... - ... - ... - - while ( ! signalled ) - waitcondition.wait( locker.mutex() ); - - ... - ... - ... - } - }; - \endcode - - \sa TQMutex, TQWaitCondition -*/ - -/*! - \fn TQMutexLocker::TQMutexLocker( TQMutex *mutex ) - - Constructs a TQMutexLocker and locks \a mutex. The mutex will be - unlocked when the TQMutexLocker is destroyed. If \a mutex is zero, - TQMutexLocker does nothing. - - \sa TQMutex::lock() -*/ - -/*! - \fn TQMutexLocker::~TQMutexLocker() - - Destroys the TQMutexLocker and unlocks the mutex which was locked - in the constructor. - - \sa TQMutexLocker::TQMutexLocker(), TQMutex::unlock() -*/ - -/*! - \fn TQMutex *TQMutexLocker::mutex() const - - Returns a pointer to the mutex which was locked in the - constructor. - - \sa TQMutexLocker::TQMutexLocker() -*/ - -#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/qmutexpool.cpp b/src/tools/qmutexpool.cpp deleted file mode 100644 index 72c66c8ca..000000000 --- a/src/tools/qmutexpool.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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. -** -**********************************************************************/ - -#include "qmutexpool_p.h" - -#ifdef TQT_THREAD_SUPPORT - -#include - -TQ_EXPORT TQMutexPool *tqt_global_mutexpool = 0; - - -/*! - \class TQMutexPool qmutexpool_p.h - \brief The TQMutexPool class provides a pool of TQMutex objects. - - \internal - - \ingroup thread - - TQMutexPool is a convenience class that provides access to a fixed - number of TQMutex objects. - - Typical use of a TQMutexPool is in situations where it is not - possible or feasible to use one TQMutex for every protected object. - The mutex pool will return a mutex based on the address of the - object that needs protection. - - For example, consider this simple class: - - \code - class Number { - public: - Number( double n ) : num ( n ) { } - - void setNumber( double n ) { num = n; } - double number() const { return num; } - - private: - double num; - }; - \endcode - - Adding a TQMutex member to the Number class does not make sense, - because it is so small. However, in order to ensure that access to - each Number is protected, you need to use a mutex. In this case, a - TQMutexPool would be ideal. - - Code to calculate the square of a number would then look something - like this: - - \code - void calcSquare( Number *num ) - { - TQMutexLocker locker( mutexpool.get( num ) ); - num.setNumber( num.number() * num.number() ); - } - \endcode - - This function will safely calculate the square of a number, since - it uses a mutex from a TQMutexPool. The mutex is locked and - unlocked automatically by the TQMutexLocker class. See the - TQMutexLocker documentation for more details. -*/ - -/*! - Constructs a TQMutexPool, reserving space for \a size TQMutexes. If - \a recursive is TRUE, all TQMutexes in the pool will be recursive - mutexes; otherwise they will all be non-recursive (the default). - - The TQMutexes are created when needed, and deleted when the - TQMutexPool is destructed. -*/ -TQMutexPool::TQMutexPool( bool recursive, int size ) - : mutex( FALSE ), count( size ), recurs( recursive ) -{ - mutexes = new TQMutex*[count]; - for ( int index = 0; index < count; ++index ) { - mutexes[index] = 0; - } -} - -/*! - Destructs a TQMutexPool. All TQMutexes that were created by the pool - are deleted. -*/ -TQMutexPool::~TQMutexPool() -{ - TQMutexLocker locker( &mutex ); - for ( int index = 0; index < count; ++index ) { - delete mutexes[index]; - mutexes[index] = 0; - } - delete [] mutexes; - mutexes = 0; -} - -/*! - Returns a TQMutex from the pool. TQMutexPool uses the value \a - address to determine which mutex is retured from the pool. -*/ -TQMutex *TQMutexPool::get( void *address ) -{ - int index = (int) ( (unsigned long) address % count ); - - if ( ! mutexes[index] ) { - // mutex not created, create one - - TQMutexLocker locker( &mutex ); - // we need to check once again that the mutex hasn't been created, since - // 2 threads could be trying to create a mutex as the same index... - if ( ! mutexes[index] ) { - mutexes[index] = new TQMutex( recurs ); - } - } - - return mutexes[index]; -} - -#endif diff --git a/src/tools/qmutexpool_p.h b/src/tools/qmutexpool_p.h deleted file mode 100644 index a0bb28562..000000000 --- a/src/tools/qmutexpool_p.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 TQMUTEXPOOL_P_H -#define TQMUTEXPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of TQSettings. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -// - -#ifdef TQT_THREAD_SUPPORT - -#ifndef QT_H -#include "ntqmutex.h" -#include "ntqmemarray.h" -#endif // QT_H - -class TQ_EXPORT TQMutexPool -{ -public: - TQMutexPool( bool recursive = FALSE, int size = 17 ); - ~TQMutexPool(); - - TQMutex *get( void *address ); - -private: - TQMutex mutex; - TQMutex **mutexes; - int count; - bool recurs; -}; - -extern TQ_EXPORT TQMutexPool *tqt_global_mutexpool; - -#endif // TQT_THREAD_SUPPORT - -#endif // TQMUTEXPOOL_P_H diff --git a/src/tools/qregexp.cpp b/src/tools/qregexp.cpp index 612e31194..e6447cdf1 100644 --- a/src/tools/qregexp.cpp +++ b/src/tools/qregexp.cpp @@ -53,8 +53,8 @@ #include "ntqtl.h" #ifdef TQT_THREAD_SUPPORT -#include "ntqthreadstorage.h" -#include +#include "tqthreadstorage.h" +#include #endif // TQT_THREAD_SUPPORT #undef TQT_TRANSLATE_NOOP diff --git a/src/tools/qsemaphore.cpp b/src/tools/qsemaphore.cpp deleted file mode 100644 index 810837b4c..000000000 --- a/src/tools/qsemaphore.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** -** -** TQSemaphore class for Unix -** -** Created : 20010725 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 "ntqsemaphore.h" -#include "ntqmutex.h" -#include "ntqwaitcondition.h" - - -/*! - \class TQSemaphore ntqsemaphore.h - \threadsafe - \brief The TQSemaphore class provides a robust integer semaphore. - - \ingroup thread - \ingroup environment - - A TQSemaphore can be used to serialize thread execution, in a - similar way to a TQMutex. A semaphore differs from a mutex, in - that a semaphore can be accessed by more than one thread at a - time. - - For example, suppose we have an application that stores data in a - large tree structure. The application creates 10 threads - (commonly called a thread pool) to perform searches on the tree. - When the application searches the tree for some piece of data, it - uses one thread per base node to do the searching. A semaphore - could be used to make sure that two threads don't try to search - the same branch of the tree at the same time. - - A non-computing example of a semaphore would be dining at a - restuarant. A semaphore is initialized to have a maximum count - equal to the number of chairs in the restuarant. As people - arrive, they want a seat. As seats are filled, the semaphore is - accessed, once per person. As people leave, the access is - released, allowing more people to enter. If a party of 10 people - want to be seated, but there are only 9 seats, those 10 people - will wait, but a party of 4 people would be seated (taking the - available seats to 5, making the party of 10 people wait longer). - - When a semaphore is created it is given a number which is the - maximum number of concurrent accesses it will permit. Accesses to - the sempahore are gained using operator++() or operator+=(), and - released with operator--() or operator-=(). The number of - accesses allowed is retrieved with available(), and the total - number with total(). Note that the incrementing functions will - block if there aren't enough available accesses. Use tryAccess() - if you want to acquire accesses without blocking. -*/ - - -class TQSemaphorePrivate { -public: - TQSemaphorePrivate(int); - - TQMutex mutex; - TQWaitCondition cond; - - int value, max; -}; - - -TQSemaphorePrivate::TQSemaphorePrivate(int m) - : mutex(FALSE), value(0), max(m) -{ -} - - -/*! - Creates a new semaphore. The semaphore can be concurrently - accessed at most \a maxcount times. -*/ -TQSemaphore::TQSemaphore(int maxcount) -{ - d = new TQSemaphorePrivate(maxcount); -} - - -/*! - Destroys the semaphore. - - \warning If you destroy a semaphore that has accesses in use the - resultant behavior is undefined. -*/ -TQSemaphore::~TQSemaphore() -{ - delete d; -} - - -/*! - Postfix ++ operator. - - Try to get access to the semaphore. If \l available() == 0, this - call will block until it can get access, i.e. until available() \> - 0. -*/ -int TQSemaphore::operator++(int) -{ - TQMutexLocker locker(&d->mutex); - while (d->value >= d->max) - d->cond.wait(locker.mutex()); - - ++d->value; - if (d->value > d->max) - d->value = d->max; - - return d->value; -} - - -/*! - Postfix -- operator. - - Release access of the semaphore. This wakes all threads waiting - for access to the semaphore. -*/ -int TQSemaphore::operator--(int) -{ - TQMutexLocker locker(&d->mutex); - - --d->value; - if (d->value < 0) - d->value = 0; - - d->cond.wakeAll(); - - return d->value; -} - - -/*! - Try to get access to the semaphore. If \l available() \< \a n, this - call will block until it can get all the accesses it wants, i.e. - until available() \>= \a n. -*/ -int TQSemaphore::operator+=(int n) -{ - TQMutexLocker locker(&d->mutex); - - if ( n < 0 || n > d->max ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQSemaphore::operator+=: paramter %d out of range", n ); -#endif // QT_CHECK_RANGE - n = n < 0 ? 0 : d->max; - } - - while (d->value + n > d->max) - d->cond.wait(locker.mutex()); - - d->value += n; - - return d->value; -} - - -/*! - Release \a n accesses to the semaphore. -*/ -int TQSemaphore::operator-=(int n) -{ - TQMutexLocker locker(&d->mutex); - - if ( n < 0 || n > d->value ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQSemaphore::operator-=: paramter %d out of range", n ); -#endif // QT_CHECK_RANGE - n = n < 0 ? 0 : d->value; - } - - d->value -= n; - d->cond.wakeAll(); - - return d->value; -} - - -/*! - Returns the number of accesses currently available to the - semaphore. -*/ -int TQSemaphore::available() const -{ - TQMutexLocker locker(&d->mutex); - return d->max - d->value; -} - - -/*! - Returns the total number of accesses to the semaphore. -*/ -int TQSemaphore::total() const -{ - TQMutexLocker locker(&d->mutex); - return d->max; -} - - -/*! - Try to get access to the semaphore. If \l available() \< \a n, this - function will return FALSE immediately. If \l available() \>= \a n, - this function will take \a n accesses and return TRUE. This - function does \e not block. -*/ -bool TQSemaphore::tryAccess(int n) -{ - TQMutexLocker locker(&d->mutex); - - if (d->value + n > d->max) - return FALSE; - - d->value += n; - - return TRUE; -} - -#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/qt_tools.pri b/src/tools/qt_tools.pri index b57e00435..d52bbd339 100644 --- a/src/tools/qt_tools.pri +++ b/src/tools/qt_tools.pri @@ -38,15 +38,15 @@ tools { $$TOOLS_P/qlocale_p.h \ $$TOOLS_H/tqptrlist.h \ $$TOOLS_H/tqmap.h \ - $$TOOLS_H/ntqmutex.h \ - $$TOOLS_P/qmutex_p.h \ - $$TOOLS_P/qmutexpool_p.h \ + $$TOOLS_H/tqmutex.h \ + $$TOOLS_P/tqmutex_p.h \ + $$TOOLS_P/tqmutexpool_p.h \ $$TOOLS_P/qpluginmanager_p.h \ $$TOOLS_H/tqptrcollection.h \ $$TOOLS_H/tqptrdict.h \ $$TOOLS_H/tqptrqueue.h \ $$TOOLS_H/ntqregexp.h \ - $$TOOLS_H/ntqsemaphore.h \ + $$TOOLS_H/tqsemaphore.h \ $$TOOLS_H/ntqsettings.h \ $$TOOLS_P/qsettings_p.h \ $$TOOLS_H/ntqshared.h \ @@ -56,14 +56,14 @@ tools { $$TOOLS_H/tqstrlist.h \ $$TOOLS_H/tqstrvec.h \ $$TOOLS_H/tqtextstream.h \ - $$TOOLS_P/qthreadinstance_p.h \ - $$TOOLS_H/ntqthreadstorage.h\ + $$TOOLS_P/tqthreadinstance_p.h \ + $$TOOLS_H/tqthreadstorage.h\ $$TOOLS_P/qunicodetables_p.h \ $$TOOLS_H/tqptrvector.h \ $$TOOLS_H/tqvaluelist.h \ $$TOOLS_H/tqvaluestack.h \ $$TOOLS_H/tqvaluevector.h \ - $$TOOLS_H/ntqwaitcondition.h \ + $$TOOLS_H/tqwaitcondition.h \ $$TOOLS_P/qcom_p.h \ $$TOOLS_P/qucom_p.h \ $$TOOLS_H/ntquuid.h @@ -73,9 +73,9 @@ tools { $$TOOLS_CPP/qfileinfo_win.cpp \ $$TOOLS_CPP/qlibrary_win.cpp \ $$TOOLS_CPP/qsettings_win.cpp \ - $$TOOLS_CPP/qmutex_win.cpp \ - $$TOOLS_CPP/qwaitcondition_win.cpp \ - $$TOOLS_CPP/qthreadstorage_win.cpp \ + $$TOOLS_CPP/tqmutex_win.cpp \ + $$TOOLS_CPP/tqwaitcondition_win.cpp \ + $$TOOLS_CPP/tqthreadstorage_win.cpp \ $$TOOLS_CPP/qcriticalsection_p.cpp win32-borland:SOURCES += $$TOOLS_CPP/qwinexport.cpp @@ -95,9 +95,9 @@ tools { else:unix:SOURCES += $$TOOLS_CPP/qdir_unix.cpp \ $$TOOLS_CPP/qfile_unix.cpp \ $$TOOLS_CPP/qfileinfo_unix.cpp \ - $$TOOLS_CPP/qmutex_unix.cpp \ - $$TOOLS_CPP/qthreadstorage_unix.cpp \ - $$TOOLS_CPP/qwaitcondition_unix.cpp + $$TOOLS_CPP/tqmutex_unix.cpp \ + $$TOOLS_CPP/tqthreadstorage_unix.cpp \ + $$TOOLS_CPP/tqwaitcondition_unix.cpp mac:!x11:!embedded:SOURCES += $$TOOLS_CPP/qsettings_mac.cpp mac { @@ -128,11 +128,11 @@ tools { $$TOOLS_CPP/qlibrary.cpp \ $$TOOLS_CPP/qlocale.cpp \ $$TOOLS_CPP/tqmap.cpp \ - $$TOOLS_CPP/qmutexpool.cpp \ + $$TOOLS_CPP/tqmutexpool.cpp \ $$TOOLS_CPP/tqptrcollection.cpp \ $$TOOLS_CPP/qregexp.cpp \ $$TOOLS_CPP/tqstring.cpp \ - $$TOOLS_CPP/qsemaphore.cpp \ + $$TOOLS_CPP/tqsemaphore.cpp \ $$TOOLS_CPP/qsettings.cpp \ $$TOOLS_CPP/tqstringlist.cpp \ $$TOOLS_CPP/tqtextstream.cpp \ diff --git a/src/tools/qthreadinstance_p.h b/src/tools/qthreadinstance_p.h deleted file mode 100644 index 076c2ba19..000000000 --- a/src/tools/qthreadinstance_p.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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_P_H -#define TQTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of TQThread and TQThreadStorage. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifdef TQT_THREAD_SUPPORT - -#ifndef QT_H -#include "ntqmutex.h" -#include "ntqwindowdefs.h" -#endif // QT_H - -#ifdef Q_OS_UNIX -#include -#endif - -class TQThread; -class TQEventLoop; - -class TQThreadInstance { -public: - static void setCurrentThread(TQThread *thread); - static TQThreadInstance *current(); - - void init(unsigned int stackSize); - void deinit(); - - TQMutex *mutex() const; - void terminate(); - - unsigned int stacksize; - void *args[2]; - void **thread_storage; - bool finished : 1; - bool running : 1; - bool orphan : 1; - -#ifdef Q_OS_UNIX - pthread_cond_t thread_done; - pthread_t thread_id; - - static void *start( void * ); - static void finish( void * ); -#endif // Q_OS_UNIX - -#ifdef Q_OS_WIN32 - TQt::HANDLE handle; - unsigned int thread_id; - int waiters; - - static unsigned int __stdcall start( void * ); - static void finish( TQThreadInstance * ); -#endif // Q_OS_WIN32 - - static void finishGuiThread( TQThreadInstance *d ); - - TQEventLoop* eventLoop; - int cleanupType; - bool disableThreadPostedEvents : 1; -}; - -#endif // TQT_THREAD_SUPPORT -#endif // TQTHREAD_P_H diff --git a/src/tools/qthreadstorage_unix.cpp b/src/tools/qthreadstorage_unix.cpp deleted file mode 100644 index 86192868e..000000000 --- a/src/tools/qthreadstorage_unix.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 "ntqapplication.h" -#include "ntqthread.h" -#include "qplatformdefs.h" - -#include "ntqthreadstorage.h" -#include - -#include - -// #define TQTHREADSTORAGE_DEBUG - - -// keep this in sync with the implementation in qthreadstorage.cpp -static const int MAX_THREAD_STORAGE = 257; // 256 maximum + 1 used in TQRegExp - -static pthread_mutex_t thread_storage_mutex = PTHREAD_MUTEX_INITIALIZER; - -static bool thread_storage_init = FALSE; -static struct { - bool used; - void (*func)( void * ); -} thread_storage_usage[MAX_THREAD_STORAGE]; - - -TQThreadStorageData::TQThreadStorageData( void (*func)( void * ) ) - : id( 0 ) -{ - pthread_mutex_lock( &thread_storage_mutex ); - - // make sure things are initialized - if ( ! thread_storage_init ) - memset( thread_storage_usage, 0, sizeof( thread_storage_usage ) ); - thread_storage_init = TRUE; - - for ( ; id < MAX_THREAD_STORAGE; ++id ) { - if ( !thread_storage_usage[id].used ) - break; - } - - Q_ASSERT( id >= 0 && id < MAX_THREAD_STORAGE ); - thread_storage_usage[id].used = TRUE; - thread_storage_usage[id].func = func; - -#ifdef TQTHREADSTORAGE_DEBUG - tqDebug( "TQThreadStorageData: allocated id %d", id ); -#endif // TQTHREADSTORAGE_DEBUG - - pthread_mutex_unlock( &thread_storage_mutex ); -} - -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; - -#ifdef TQTHREADSTORAGE_DEBUG - tqDebug( "TQThreadStorageData: released id %d", id ); -#endif // TQTHREADSTORAGE_DEBUG - - pthread_mutex_unlock( &thread_storage_mutex ); -} - -void **TQThreadStorageData::get() const -{ - TQThreadInstance *d = TQThreadInstance::current(); - if (!d) { - tqWarning("TQThreadStorage can only be used with threads started with TQThread"); - return 0; - } - TQMutexLocker locker( d->mutex() ); - return d->thread_storage && d->thread_storage[id] ? &d->thread_storage[id] : 0; -} - -void **TQThreadStorageData::set( void *p ) -{ - TQThreadInstance *d = TQThreadInstance::current(); - if (!d) { - tqWarning("TQThreadStorage can only be used with threads started with TQThread"); - return 0; - } - TQMutexLocker locker( d->mutex() ); - if ( !d->thread_storage ) { -#ifdef TQTHREADSTORAGE_DEBUG - tqDebug( "TQThreadStorageData: allocating storage for thread %lx", - (unsigned long) pthread_self() ); -#endif // TQTHREADSTORAGE_DEBUG - - d->thread_storage = new void*[MAX_THREAD_STORAGE]; - memset( d->thread_storage, 0, sizeof( void* ) * MAX_THREAD_STORAGE ); - } - - // delete any previous data - if ( d->thread_storage[id] ) - thread_storage_usage[id].func( d->thread_storage[id] ); - - // store new data - d->thread_storage[id] = p; - return &d->thread_storage[id]; -} - -void TQThreadStorageData::finish( void **thread_storage ) -{ - if ( ! thread_storage ) return; // nothing to do - -#ifdef TQTHREADSTORAGE_DEBUG - tqDebug( "TQThreadStorageData: destroying storage for thread %lx", - (unsigned long) pthread_self() ); -#endif // TQTHREADSTORAGE_DEBUG - - for ( int i = 0; i < MAX_THREAD_STORAGE; ++i ) { - if ( ! thread_storage[i] ) continue; - if ( ! thread_storage_usage[i].used ) { -#ifdef QT_CHECK_STATE - tqWarning( "TQThreadStorage: thread %lx exited after TQThreadStorage destroyed", - (unsigned long) pthread_self() ); -#endif // QT_CHECK_STATE - continue; - } - - thread_storage_usage[i].func( thread_storage[i] ); - } - - delete [] thread_storage; -} - - -/*! - \class TQThreadStorage - \brief The TQThreadStorage class provides per-thread data storage. - - \threadsafe - \ingroup thread - \ingroup environment - - TQThreadStorage is a template class that provides per-thread data - storage. - - \e{Note that due to compiler limitations, TQThreadStorage can only - store pointers.} - - The setLocalData() function stores a single thread-specific value - for the calling thread. The data can be accessed later using the - localData() functions. TQThreadStorage takes ownership of the - data (which must be created on the heap with \e new) and deletes - it when the thread exits (either normally or via termination). - - The hasLocalData() function allows the programmer to determine if - data has previously been set using the setLocalData() function. - This is useful for lazy initializiation. - - For example, the following code uses TQThreadStorage to store a - single cache for each thread that calls the \e cacheObject() and - \e removeFromCache() functions. The cache is automatically - deleted when the calling thread exits (either normally or via - termination). - - \code - TQThreadStorage *> caches; - - void cacheObject( const TQString &key, SomeClass *object ) - { - if ( ! caches.hasLocalData() ) - caches.setLocalData( new TQCache ); - - caches.localData()->insert( key, object ); - } - - void removeFromCache( const TQString &key ) - { - if ( ! caches.hasLocalData() ) - return; // nothing to do - - caches.localData()->remove( key ); - } - \endcode - - \section1 Caveats - - \list - - \i As noted above, TQThreadStorage can only store pointers due to - compiler limitations. Support for value-based objects will be - added when the majority of compilers are able to support partial - template specialization. - - \i The \link ~TQThreadStorage() destructor\endlink does \e not - delete per-thread data. TQThreadStorage only deletes per-thread - data when the thread exits or when setLocalData() is called - multiple times. - - \i TQThreadStorage can only be used with threads started with - TQThread. It \e cannot be used with threads started with - platform-specific APIs. - - \i As a corollary to the above, platform-specific APIs cannot be - used to exit or terminate a TQThread using TQThreadStorage. Doing so - will cause all per-thread data to be leaked. See TQThread::exit() - and TQThread::terminate(). - - \i TQThreadStorage \e can be used to store data for the \e main() - thread \e after TQApplication has been constructed. TQThreadStorage - deletes all data set for the \e main() thread when TQApplication is - destroyed, regardless of whether or not the \e main() thread has - actually finished. - - \i The implementation of TQThreadStorage limits the total number of - TQThreadStorage objects to 256. An unlimited number of threads - can store per-thread data in each TQThreadStorage object. - - \endlist -*/ - -/*! - \fn TQThreadStorage::TQThreadStorage() - - Constructs a new per-thread data storage object. -*/ - -/*! - \fn TQThreadStorage::~TQThreadStorage() - - Destroys the per-thread data storage object. - - Note: The per-thread data stored is \e not deleted. Any data left - in TQThreadStorage is leaked. Make sure that all threads using - TQThreadStorage have exited before deleting the TQThreadStorage. - - \sa hasLocalData() -*/ - -/*! - \fn bool TQThreadStorage::hasLocalData() const - - Returns TRUE if the calling thread has non-zero data available; - otherwise returns FALSE. - - \sa localData() -*/ - -/*! - \fn T& TQThreadStorage::localData() - - Returns a reference to the data that was set by the calling - thread. - - Note: TQThreadStorage can only store pointers. This function - returns a \e reference to the pointer that was set by the calling - thread. The value of this reference is 0 if no data was set by - the calling thread, - - \sa hasLocalData() -*/ -/* - ### addition to the above documentation when we start supporting - ### partial template specialization, and TQThreadStorage can store - ### values *and* pointers - - When using TQThreadStorage to store values (not pointers), this - function stores an object of type \e T (created with its default - constructor) and returns a reference to that object. -*/ - -/*! - \fn const T TQThreadStorage::localData() const - \overload - - Returns a copy of the data that was set by the calling thread. - - Note: TQThreadStorage can only store pointers. This function - returns a pointer to the data that was set by the calling thread. - If no data was set by the calling thread, this function returns 0. - - \sa hasLocalData() -*/ -/* - ### addition to the above documentation when we start supporting - ### partial template specialization, and TQThreadStorage can store - ### values *and* pointers - - When using TQThreadStorage to store values (not pointers), this - function returns an object of type \e T (created with its default - constructor). Unlike the above function, this object is \e not - stored automatically. You will need to call setLocalData() to store - the object. -*/ - -/*! - \fn void TQThreadStorage::setLocalData( T data ) - - Sets the local data for the calling thread to \a data. It can be - accessed later using the localData() functions. - - If \a data is 0, this function deletes the previous data (if - any) and returns immediately. - - If \a data is non-zero, TQThreadStorage takes ownership of the \a - data and deletes it automatically either when the thread exits - (either normally or via termination) or when setLocalData() is - called again. - - Note: TQThreadStorage can only store pointers. The \a data - argument must be either a pointer to an object created on the heap - (i.e. using \e new) or 0. You should not delete \a data - yourself; TQThreadStorage takes ownership and will delete the \a - data itself. - - \sa localData() hasLocalData() -*/ - -#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/qwaitcondition_unix.cpp b/src/tools/qwaitcondition_unix.cpp deleted file mode 100644 index 62038bae5..000000000 --- a/src/tools/qwaitcondition_unix.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** TQWaitCondition class for Unix -** -** Created : 20010725 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools 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 "ntqwaitcondition.h" -#include "ntqmutex.h" -#include "qmutex_p.h" - -#include -#include - - -struct TQWaitConditionPrivate { - pthread_cond_t cond; -}; - - -/*! - \class TQWaitCondition ntqwaitcondition.h - \threadsafe - \brief The TQWaitCondition class allows waiting/waking for conditions between threads. - - \ingroup thread - \ingroup environment - - TQWaitConditions allow a thread to tell other threads that some - sort of condition has been met; one or many threads can block - waiting for a TQWaitCondition to set a condition with wakeOne() or - wakeAll(). Use wakeOne() to wake one randomly selected event or - wakeAll() to wake them all. For example, say we have three tasks - that should be performed every time the user presses a key; each - task could be split into a thread, each of which would have a - run() body like this: - - \code - TQWaitCondition key_pressed; - - for (;;) { - key_pressed.wait(); // This is a TQWaitCondition global variable - // Key was pressed, do something interesting - do_something(); - } - \endcode - - A fourth thread would read key presses and wake the other three - threads up every time it receives one, like this: - - \code - TQWaitCondition key_pressed; - - for (;;) { - getchar(); - // Causes any thread in key_pressed.wait() to return from - // that method and continue processing - key_pressed.wakeAll(); - } - \endcode - - Note that the order the three threads are woken up in is - undefined, and that if some or all of the threads are still in - do_something() when the key is pressed, they won't be woken up - (since they're not waiting on the condition variable) and so the - task will not be performed for that key press. This can be - avoided by, for example, doing something like this: - - \code - TQMutex mymutex; - TQWaitCondition key_pressed; - int mycount=0; - - // Worker thread code - for (;;) { - key_pressed.wait(); // This is a TQWaitCondition global variable - mymutex.lock(); - mycount++; - mymutex.unlock(); - do_something(); - mymutex.lock(); - mycount--; - mymutex.unlock(); - } - - // Key reading thread code - for (;;) { - getchar(); - mymutex.lock(); - // Sleep until there are no busy worker threads - while( mycount > 0 ) { - mymutex.unlock(); - sleep( 1 ); - mymutex.lock(); - } - mymutex.unlock(); - key_pressed.wakeAll(); - } - \endcode - - The mutexes are necessary because the results of two threads - attempting to change the value of the same variable simultaneously - are unpredictable. -*/ - -/*! - Constructs a new event signalling, i.e. wait condition, object. -*/ -TQWaitCondition::TQWaitCondition() -{ - d = new TQWaitConditionPrivate; - - int ret = pthread_cond_init(&d->cond, NULL); - -#ifdef QT_CHECK_RANGE - if (ret) - tqWarning( "Wait condition init failure: %s", strerror( ret ) ); -#endif -} - - -/*! - Deletes the event signalling, i.e. wait condition, object. -*/ -TQWaitCondition::~TQWaitCondition() -{ - int ret = pthread_cond_destroy(&d->cond); - - if (ret) { -#ifdef QT_CHECK_RANGE - tqWarning( "Wait condition destroy failure: %s", strerror( ret ) ); -#endif - - // seems we have threads waiting on us, lets wake them up - pthread_cond_broadcast(&d->cond); - } - - delete d; -} - -/*! - This wakes one thread waiting on the TQWaitCondition. The thread - that is woken up depends on the operating system's scheduling - policies, and cannot be controlled or predicted. - - \sa wakeAll() -*/ -void TQWaitCondition::wakeOne() -{ - int ret = pthread_cond_signal(&d->cond); - -#ifdef QT_CHECK_RANGE - if (ret) - tqWarning("Wait condition wakeOne failure: %s", strerror(ret)); -#endif -} - -/*! - This wakes all threads waiting on the TQWaitCondition. The order in - which the threads are woken up depends on the operating system's - scheduling policies, and cannot be controlled or predicted. - - \sa wakeOne() -*/ -void TQWaitCondition::wakeAll() -{ - int ret = pthread_cond_broadcast(&d->cond); - -#ifdef QT_CHECK_RANGE - if (ret) - tqWarning("Wait condition wakeAll failure: %s", strerror(ret)); -#endif -} - -/*! - Wait on the thread event object. The thread calling this will - block until either of these conditions is met: - \list - \i Another thread signals it using wakeOne() or wakeAll(). This - function will return TRUE in this case. - \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the - default), then the wait will never timeout (the event must be - signalled). This function will return FALSE if the wait timed - out. - \endlist - - \sa wakeOne(), wakeAll() -*/ -bool TQWaitCondition::wait(unsigned long time) -{ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock( &mutex ); - - 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->cond, &mutex, &ti); - } else - ret = pthread_cond_wait(&d->cond, &mutex); - -#ifdef QT_CHECK_RANGE - if (ret && ret != ETIMEDOUT) - tqWarning("Wait condition wait failure: %s",strerror(ret)); -#endif - - pthread_mutex_unlock( &mutex ); - - return (ret == 0); -} - -/*! - \overload - - Release the locked \a mutex and wait on the thread event object. - The \a mutex must be initially locked by the calling thread. If \a - mutex is not in a locked state, this function returns immediately. - If \a mutex is a recursive mutex, this function returns - immediately. The \a mutex will be unlocked, and the calling thread - will block until either of these conditions is met: - \list - \i Another thread signals it using wakeOne() or wakeAll(). This - function will return TRUE in this case. - \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the - default), then the wait will never timeout (the event must be - signalled). This function will return FALSE if the wait timed - out. - \endlist - - The mutex will be returned to the same locked state. This function - is provided to allow the atomic transition from the locked state - to the wait state. - - \sa wakeOne(), wakeAll() -*/ -bool TQWaitCondition::wait(TQMutex *mutex, unsigned long time) -{ - if (! mutex) - return FALSE; - - if (mutex->d->type() == Q_MUTEX_RECURSIVE) { -#ifdef QT_CHECK_RANGE - tqWarning("Wait condition warning: using recursive mutexes with\n" - " wait conditions is undefined!"); -#endif - return FALSE; - } - - 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->cond, &mutex->d->handle, &ti); - } else - ret = pthread_cond_wait(&d->cond, &mutex->d->handle); - -#ifdef QT_CHECK_RANGE - if (ret && ret != ETIMEDOUT) - tqWarning("Wait condition wait failure: %s",strerror(ret)); -#endif - - return (ret == 0); -} - -#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/tqmutex.h b/src/tools/tqmutex.h new file mode 100644 index 000000000..c517c6355 --- /dev/null +++ b/src/tools/tqmutex.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Definition of TQMutex class +** +** Created : 931107 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQMUTEX_H +#define TQMUTEX_H + +#ifndef QT_H +#include "ntqglobal.h" +#endif // QT_H + +#if defined(TQT_THREAD_SUPPORT) + +class TQMutexPrivate; + +const int Q_MUTEX_NORMAL = 0; +const int Q_MUTEX_RECURSIVE = 1; + +class TQ_EXPORT TQMutex +{ + friend class TQThread; + friend class TQWaitCondition; + friend class TQWaitConditionPrivate; + +public: + TQMutex(bool recursive = FALSE); + virtual ~TQMutex(); + + void lock(); + void unlock(); + bool locked(); + bool tryLock(); + +private: + TQMutexPrivate * d; + +#if defined(TQ_DISABLE_COPY) + TQMutex( const TQMutex & ); + TQMutex &operator=( const TQMutex & ); +#endif + +public: + int level(); +}; + +class TQ_EXPORT TQMutexLocker +{ +public: + TQMutexLocker( TQMutex * ); + ~TQMutexLocker(); + + TQMutex *mutex() const; + +private: + TQMutex *mtx; + +#if defined(TQ_DISABLE_COPY) + TQMutexLocker( const TQMutexLocker & ); + TQMutexLocker &operator=( const TQMutexLocker & ); +#endif +}; + +inline TQMutexLocker::TQMutexLocker( TQMutex *m ) + : mtx( m ) +{ + if ( mtx ) mtx->lock(); +} + +inline TQMutexLocker::~TQMutexLocker() +{ + if ( mtx ) mtx->unlock(); +} + +inline TQMutex *TQMutexLocker::mutex() const +{ + return mtx; +} + +#endif + +#endif diff --git a/src/tools/tqmutex_p.h b/src/tools/tqmutex_p.h new file mode 100644 index 000000000..ee841f5e2 --- /dev/null +++ b/src/tools/tqmutex_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** TQMutex private class declarations +** +** Created : 20012507 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQMUTEX_P_H +#define TQMUTEX_P_H + +#ifndef QT_H +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of tqmutex_unix.cpp and tqmutex_win.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// + +class TQMutexPrivate { +public: + // Q_MUTEX_T is defined in the various *.cpp files + Q_MUTEX_T handle; + + virtual ~TQMutexPrivate(); + + virtual void lock() = 0; + virtual void unlock() = 0; + virtual bool locked() = 0; + virtual bool trylock() = 0; + virtual int type() const = 0; + virtual int level() = 0; +}; + + +#endif // TQMUTEX_P_H diff --git a/src/tools/tqmutex_unix.cpp b/src/tools/tqmutex_unix.cpp new file mode 100644 index 000000000..9c793a02d --- /dev/null +++ b/src/tools/tqmutex_unix.cpp @@ -0,0 +1,535 @@ +/**************************************************************************** +** +** TQMutex class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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; + +#if defined(QT_CHECK_RANGE) +# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK +#else +# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT +#endif +#define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE + +#include "tqmutex.h" +#include "tqmutex_p.h" + +#include +#include + +// Private class declarations + +class TQRealMutexPrivate : public TQMutexPrivate { +public: + TQRealMutexPrivate(bool = FALSE); + + void lock(); + void unlock(); + bool locked(); + bool trylock(); + int type() const; + int level(); + + bool recursive; + int count; +}; + + +// Private class implementation + +// base destructor +TQMutexPrivate::~TQMutexPrivate() +{ + int ret = pthread_mutex_destroy(&handle); + +#ifdef QT_CHECK_RANGE + if ( ret ) + tqWarning( "Mutex destroy failure: %s", strerror( ret ) ); +#endif +} + +// real mutex class +TQRealMutexPrivate::TQRealMutexPrivate(bool recurs) + : recursive(recurs), count(0) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); + int ret = pthread_mutex_init(&handle, &attr); + pthread_mutexattr_destroy(&attr); + +#ifdef QT_CHECK_RANGE + if( ret ) + tqWarning( "Mutex init failure: %s", strerror( ret ) ); +#endif // QT_CHECK_RANGE +} + +void TQRealMutexPrivate::lock() +{ + int ret = pthread_mutex_lock(&handle); + + if (!ret) { + count++; + } else { +#ifdef QT_CHECK_RANGE + tqWarning("Mutex lock failure: %s", strerror(ret)); +#endif + } +} + +void TQRealMutexPrivate::unlock() +{ + count--; + int ret = pthread_mutex_unlock(&handle); + + if (ret) { + count++; +#ifdef QT_CHECK_RANGE + tqWarning("Mutex unlock failure: %s", strerror(ret)); +#endif + } +} + +bool TQRealMutexPrivate::locked() +{ + return count > 0; +} + +bool TQRealMutexPrivate::trylock() +{ + int ret = pthread_mutex_trylock(&handle); + + if (ret == EBUSY) { + return FALSE; + } else if (ret) { +#ifdef QT_CHECK_RANGE + tqWarning("Mutex trylock failure: %s", strerror(ret)); +#endif + return FALSE; + } + + return TRUE; +} + +int TQRealMutexPrivate::type() const +{ + return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; +} + +int TQRealMutexPrivate::level() +{ + return count; +} + + +/*! + \class TQMutex tqmutex.h + \threadsafe + \brief The TQMutex class provides access serialization between threads. + + \ingroup thread + \ingroup environment + + The purpose of a TQMutex is to protect an object, data structure or + section of code so that only one thread can access it at a time + (This is similar to the Java \c synchronized keyword). For + example, say there is a method which prints a message to the user + on two lines: + + \code + int number = 6; + + void method1() + { + number *= 5; + number /= 4; + } + + void method2() + { + number *= 3; + number /= 2; + } + \endcode + + If these two methods are called in succession, the following happens: + + \code + // method1() + number *= 5; // number is now 30 + number /= 4; // number is now 7 + + // method2() + number *= 3; // nubmer is now 21 + number /= 2; // number is now 10 + \endcode + + If these two methods are called simultaneously from two threads then the + following sequence could result: + + \code + // Thread 1 calls method1() + number *= 5; // number is now 30 + + // Thread 2 calls method2(). + // + // Most likely Thread 1 has been put to sleep by the operating + // system to allow Thread 2 to run. + number *= 3; // number is now 90 + number /= 2; // number is now 45 + + // Thread 1 finishes executing. + number /= 4; // number is now 11, instead of 10 + \endcode + + If we add a mutex, we should get the result we want: + + \code + TQMutex mutex; + int number = 6; + + void method1() + { + mutex.lock(); + number *= 5; + number /= 4; + mutex.unlock(); + } + + void method2() + { + mutex.lock(); + number *= 3; + number /= 2; + mutex.unlock(); + } + \endcode + + Then only one thread can modify \c number at any given time and + the result is correct. This is a trivial example, of course, but + applies to any other case where things need to happen in a + particular sequence. + + When you call lock() in a thread, other threads that try to call + lock() in the same place will block until the thread that got the + lock calls unlock(). A non-blocking alternative to lock() is + tryLock(). +*/ + +/*! + Constructs a new mutex. The mutex is created in an unlocked state. + A recursive mutex is created if \a recursive is TRUE; a normal + mutex is created if \a recursive is FALSE (the default). With a + recursive mutex, a thread can lock the same mutex multiple times + and it will not be unlocked until a corresponding number of + unlock() calls have been made. +*/ +TQMutex::TQMutex(bool recursive) +{ + d = new TQRealMutexPrivate(recursive); +} + +/*! + Destroys the mutex. + + \warning If you destroy a mutex that still holds a lock the + resultant behavior is undefined. +*/ +TQMutex::~TQMutex() +{ + delete d; +} + +/*! + Attempt to lock the mutex. If another thread has locked the mutex + then this call will \e block until that thread has unlocked it. + + \sa unlock(), locked() +*/ +void TQMutex::lock() +{ + d->lock(); +} + +/*! + Unlocks the mutex. Attempting to unlock a mutex in a different + thread to the one that locked it results in an error. Unlocking a + mutex that is not locked results in undefined behaviour (varies + between different Operating Systems' thread implementations). + + \sa lock(), locked() +*/ +void TQMutex::unlock() +{ + d->unlock(); +} + +/*! + Returns TRUE if the mutex is locked by another thread; otherwise + returns FALSE. + + \warning Due to differing implementations of recursive mutexes on + various platforms, calling this function from the same thread that + previously locked the mutex will return undefined results. + + \sa lock(), unlock() +*/ +bool TQMutex::locked() +{ + return d->locked(); +} + +/*! + Attempt to lock the mutex. If the lock was obtained, this function + returns TRUE. If another thread has locked the mutex, this + function returns FALSE, instead of waiting for the mutex to become + available, i.e. it does not block. + + If the lock was obtained, the mutex must be unlocked with unlock() + before another thread can successfully lock it. + + \sa lock(), unlock(), locked() +*/ +bool TQMutex::tryLock() +{ + return d->trylock(); +} + +/*! + Returns the current lock level of the mutex. + 0 means the mutex is unlocked + This method should only be called when the mutex has already been locked + by lock(), otherwise the lock level could change before the next line + of code is executed. + + WARNING: Non-recursive mutexes will never exceed a lock level of 1! + + \sa lock(), unlock(), locked() +*/ +int TQMutex::level() +{ + return d->level(); +} + +/*! + \class TQMutexLocker tqmutex.h + \brief The TQMutexLocker class simplifies locking and unlocking TQMutexes. + + \threadsafe + + \ingroup thread + \ingroup environment + + The purpose of TQMutexLocker is to simplify TQMutex locking and + unlocking. Locking and unlocking a TQMutex in complex functions and + statements or in exception handling code is error prone and + difficult to debug. TQMutexLocker should be used in such situations + to ensure that the state of the mutex is well defined and always + locked and unlocked properly. + + TQMutexLocker should be created within a function where a TQMutex + needs to be locked. The mutex is locked when TQMutexLocker is + created, and unlocked when TQMutexLocker is destroyed. + + For example, this complex function locks a TQMutex upon entering + the function and unlocks the mutex at all the exit points: + + \code + int complexFunction( int flag ) + { + mutex.lock(); + + int return_value = 0; + + switch ( flag ) { + case 0: + case 1: + { + mutex.unlock(); + return moreComplexFunction( flag ); + } + + case 2: + { + int status = anotherFunction(); + if ( status < 0 ) { + mutex.unlock(); + return -2; + } + return_value = status + flag; + break; + } + + default: + { + if ( flag > 10 ) { + mutex.unlock(); + return -1; + } + break; + } + } + + mutex.unlock(); + return return_value; + } + \endcode + + This example function will get more complicated as it is + developed, which increases the likelihood that errors will occur. + + Using TQMutexLocker greatly simplifies the code, and makes it more + readable: + + \code + int complexFunction( int flag ) + { + TQMutexLocker locker( &mutex ); + + int return_value = 0; + + switch ( flag ) { + case 0: + case 1: + { + return moreComplexFunction( flag ); + } + + case 2: + { + int status = anotherFunction(); + if ( status < 0 ) + return -2; + return_value = status + flag; + break; + } + + default: + { + if ( flag > 10 ) + return -1; + break; + } + } + + return return_value; + } + \endcode + + Now, the mutex will always be unlocked when the TQMutexLocker + object is destroyed (when the function returns since \c locker is + an auto variable). Note that the mutex will be unlocked after + the call to moreComplexFunction() in this example, avoiding + possible bugs caused by unlocking the mutex too early, as in + the first example. + + The same principle applies to code that throws and catches + exceptions. An exception that is not caught in the function that + has locked the mutex has no way of unlocking the mutex before the + exception is passed up the stack to the calling function. + + TQMutexLocker also provides a mutex() member function that returns + the mutex on which the TQMutexLocker is operating. This is useful + for code that needs access to the mutex, such as + TQWaitCondition::wait(). For example: + + \code + class SignalWaiter + { + private: + TQMutexLocker locker; + + public: + SignalWaiter( TQMutex *mutex ) + : locker( mutex ) + { + } + + void waitForSignal() + { + ... + ... + ... + + while ( ! signalled ) + waitcondition.wait( locker.mutex() ); + + ... + ... + ... + } + }; + \endcode + + \sa TQMutex, TQWaitCondition +*/ + +/*! + \fn TQMutexLocker::TQMutexLocker( TQMutex *mutex ) + + Constructs a TQMutexLocker and locks \a mutex. The mutex will be + unlocked when the TQMutexLocker is destroyed. If \a mutex is zero, + TQMutexLocker does nothing. + + \sa TQMutex::lock() +*/ + +/*! + \fn TQMutexLocker::~TQMutexLocker() + + Destroys the TQMutexLocker and unlocks the mutex which was locked + in the constructor. + + \sa TQMutexLocker::TQMutexLocker(), TQMutex::unlock() +*/ + +/*! + \fn TQMutex *TQMutexLocker::mutex() const + + Returns a pointer to the mutex which was locked in the + constructor. + + \sa TQMutexLocker::TQMutexLocker() +*/ + +#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/tqmutexpool.cpp b/src/tools/tqmutexpool.cpp new file mode 100644 index 000000000..a7b17da3d --- /dev/null +++ b/src/tools/tqmutexpool.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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. +** +**********************************************************************/ + +#include "tqmutexpool_p.h" + +#ifdef TQT_THREAD_SUPPORT + +#include + +TQ_EXPORT TQMutexPool *tqt_global_mutexpool = 0; + + +/*! + \class TQMutexPool tqmutexpool_p.h + \brief The TQMutexPool class provides a pool of TQMutex objects. + + \internal + + \ingroup thread + + TQMutexPool is a convenience class that provides access to a fixed + number of TQMutex objects. + + Typical use of a TQMutexPool is in situations where it is not + possible or feasible to use one TQMutex for every protected object. + The mutex pool will return a mutex based on the address of the + object that needs protection. + + For example, consider this simple class: + + \code + class Number { + public: + Number( double n ) : num ( n ) { } + + void setNumber( double n ) { num = n; } + double number() const { return num; } + + private: + double num; + }; + \endcode + + Adding a TQMutex member to the Number class does not make sense, + because it is so small. However, in order to ensure that access to + each Number is protected, you need to use a mutex. In this case, a + TQMutexPool would be ideal. + + Code to calculate the square of a number would then look something + like this: + + \code + void calcSquare( Number *num ) + { + TQMutexLocker locker( mutexpool.get( num ) ); + num.setNumber( num.number() * num.number() ); + } + \endcode + + This function will safely calculate the square of a number, since + it uses a mutex from a TQMutexPool. The mutex is locked and + unlocked automatically by the TQMutexLocker class. See the + TQMutexLocker documentation for more details. +*/ + +/*! + Constructs a TQMutexPool, reserving space for \a size TQMutexes. If + \a recursive is TRUE, all TQMutexes in the pool will be recursive + mutexes; otherwise they will all be non-recursive (the default). + + The TQMutexes are created when needed, and deleted when the + TQMutexPool is destructed. +*/ +TQMutexPool::TQMutexPool( bool recursive, int size ) + : mutex( FALSE ), count( size ), recurs( recursive ) +{ + mutexes = new TQMutex*[count]; + for ( int index = 0; index < count; ++index ) { + mutexes[index] = 0; + } +} + +/*! + Destructs a TQMutexPool. All TQMutexes that were created by the pool + are deleted. +*/ +TQMutexPool::~TQMutexPool() +{ + TQMutexLocker locker( &mutex ); + for ( int index = 0; index < count; ++index ) { + delete mutexes[index]; + mutexes[index] = 0; + } + delete [] mutexes; + mutexes = 0; +} + +/*! + Returns a TQMutex from the pool. TQMutexPool uses the value \a + address to determine which mutex is retured from the pool. +*/ +TQMutex *TQMutexPool::get( void *address ) +{ + int index = (int) ( (unsigned long) address % count ); + + if ( ! mutexes[index] ) { + // mutex not created, create one + + TQMutexLocker locker( &mutex ); + // we need to check once again that the mutex hasn't been created, since + // 2 threads could be trying to create a mutex as the same index... + if ( ! mutexes[index] ) { + mutexes[index] = new TQMutex( recurs ); + } + } + + return mutexes[index]; +} + +#endif diff --git a/src/tools/tqmutexpool_p.h b/src/tools/tqmutexpool_p.h new file mode 100644 index 000000000..28a7ac63a --- /dev/null +++ b/src/tools/tqmutexpool_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQMUTEXPOOL_P_H +#define TQMUTEXPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of TQSettings. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifdef TQT_THREAD_SUPPORT + +#ifndef QT_H +#include "tqmutex.h" +#include "ntqmemarray.h" +#endif // QT_H + +class TQ_EXPORT TQMutexPool +{ +public: + TQMutexPool( bool recursive = FALSE, int size = 17 ); + ~TQMutexPool(); + + TQMutex *get( void *address ); + +private: + TQMutex mutex; + TQMutex **mutexes; + int count; + bool recurs; +}; + +extern TQ_EXPORT TQMutexPool *tqt_global_mutexpool; + +#endif // TQT_THREAD_SUPPORT + +#endif // TQMUTEXPOOL_P_H diff --git a/src/tools/tqsemaphore.cpp b/src/tools/tqsemaphore.cpp new file mode 100644 index 000000000..a5cdfc630 --- /dev/null +++ b/src/tools/tqsemaphore.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** TQSemaphore class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 "tqsemaphore.h" +#include "tqmutex.h" +#include "tqwaitcondition.h" + + +/*! + \class TQSemaphore tqsemaphore.h + \threadsafe + \brief The TQSemaphore class provides a robust integer semaphore. + + \ingroup thread + \ingroup environment + + A TQSemaphore can be used to serialize thread execution, in a + similar way to a TQMutex. A semaphore differs from a mutex, in + that a semaphore can be accessed by more than one thread at a + time. + + For example, suppose we have an application that stores data in a + large tree structure. The application creates 10 threads + (commonly called a thread pool) to perform searches on the tree. + When the application searches the tree for some piece of data, it + uses one thread per base node to do the searching. A semaphore + could be used to make sure that two threads don't try to search + the same branch of the tree at the same time. + + A non-computing example of a semaphore would be dining at a + restuarant. A semaphore is initialized to have a maximum count + equal to the number of chairs in the restuarant. As people + arrive, they want a seat. As seats are filled, the semaphore is + accessed, once per person. As people leave, the access is + released, allowing more people to enter. If a party of 10 people + want to be seated, but there are only 9 seats, those 10 people + will wait, but a party of 4 people would be seated (taking the + available seats to 5, making the party of 10 people wait longer). + + When a semaphore is created it is given a number which is the + maximum number of concurrent accesses it will permit. Accesses to + the sempahore are gained using operator++() or operator+=(), and + released with operator--() or operator-=(). The number of + accesses allowed is retrieved with available(), and the total + number with total(). Note that the incrementing functions will + block if there aren't enough available accesses. Use tryAccess() + if you want to acquire accesses without blocking. +*/ + + +class TQSemaphorePrivate { +public: + TQSemaphorePrivate(int); + + TQMutex mutex; + TQWaitCondition cond; + + int value, max; +}; + + +TQSemaphorePrivate::TQSemaphorePrivate(int m) + : mutex(FALSE), value(0), max(m) +{ +} + + +/*! + Creates a new semaphore. The semaphore can be concurrently + accessed at most \a maxcount times. +*/ +TQSemaphore::TQSemaphore(int maxcount) +{ + d = new TQSemaphorePrivate(maxcount); +} + + +/*! + Destroys the semaphore. + + \warning If you destroy a semaphore that has accesses in use the + resultant behavior is undefined. +*/ +TQSemaphore::~TQSemaphore() +{ + delete d; +} + + +/*! + Postfix ++ operator. + + Try to get access to the semaphore. If \l available() == 0, this + call will block until it can get access, i.e. until available() \> + 0. +*/ +int TQSemaphore::operator++(int) +{ + TQMutexLocker locker(&d->mutex); + while (d->value >= d->max) + d->cond.wait(locker.mutex()); + + ++d->value; + if (d->value > d->max) + d->value = d->max; + + return d->value; +} + + +/*! + Postfix -- operator. + + Release access of the semaphore. This wakes all threads waiting + for access to the semaphore. +*/ +int TQSemaphore::operator--(int) +{ + TQMutexLocker locker(&d->mutex); + + --d->value; + if (d->value < 0) + d->value = 0; + + d->cond.wakeAll(); + + return d->value; +} + + +/*! + Try to get access to the semaphore. If \l available() \< \a n, this + call will block until it can get all the accesses it wants, i.e. + until available() \>= \a n. +*/ +int TQSemaphore::operator+=(int n) +{ + TQMutexLocker locker(&d->mutex); + + if ( n < 0 || n > d->max ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQSemaphore::operator+=: paramter %d out of range", n ); +#endif // QT_CHECK_RANGE + n = n < 0 ? 0 : d->max; + } + + while (d->value + n > d->max) + d->cond.wait(locker.mutex()); + + d->value += n; + + return d->value; +} + + +/*! + Release \a n accesses to the semaphore. +*/ +int TQSemaphore::operator-=(int n) +{ + TQMutexLocker locker(&d->mutex); + + if ( n < 0 || n > d->value ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQSemaphore::operator-=: paramter %d out of range", n ); +#endif // QT_CHECK_RANGE + n = n < 0 ? 0 : d->value; + } + + d->value -= n; + d->cond.wakeAll(); + + return d->value; +} + + +/*! + Returns the number of accesses currently available to the + semaphore. +*/ +int TQSemaphore::available() const +{ + TQMutexLocker locker(&d->mutex); + return d->max - d->value; +} + + +/*! + Returns the total number of accesses to the semaphore. +*/ +int TQSemaphore::total() const +{ + TQMutexLocker locker(&d->mutex); + return d->max; +} + + +/*! + Try to get access to the semaphore. If \l available() \< \a n, this + function will return FALSE immediately. If \l available() \>= \a n, + this function will take \a n accesses and return TRUE. This + function does \e not block. +*/ +bool TQSemaphore::tryAccess(int n) +{ + TQMutexLocker locker(&d->mutex); + + if (d->value + n > d->max) + return FALSE; + + d->value += n; + + return TRUE; +} + +#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/tqsemaphore.h b/src/tools/tqsemaphore.h new file mode 100644 index 000000000..0dc8e81de --- /dev/null +++ b/src/tools/tqsemaphore.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Definition of TQSemaphore class +** +** Created : 931107 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQSEMAPHORE_H +#define TQSEMAPHORE_H + +#ifndef QT_H +#include "ntqglobal.h" +#endif // QT_H + +#if defined(TQT_THREAD_SUPPORT) + +class TQSemaphorePrivate; + +class TQ_EXPORT TQSemaphore +{ +public: + TQSemaphore( int ); + virtual ~TQSemaphore(); + + int available() const; + int total() const; + + // postfix operators + int operator++(int); + int operator--(int); + + int operator+=(int); + int operator-=(int); + + bool tryAccess(int); + +private: + TQSemaphorePrivate *d; + +#if defined(TQ_DISABLE_COPY) + TQSemaphore(const TQSemaphore &); + TQSemaphore &operator=(const TQSemaphore &); +#endif +}; + +#endif + +#endif diff --git a/src/tools/tqstring.cpp b/src/tools/tqstring.cpp index dbf179404..71eced17d 100644 --- a/src/tools/tqstring.cpp +++ b/src/tools/tqstring.cpp @@ -94,7 +94,7 @@ #endif #if defined(TQT_THREAD_SUPPORT) && defined(MAKE_QSTRING_THREAD_SAFE) -#include "ntqmutex.h" +#include "tqmutex.h" #endif // TQT_THREAD_SUPPORT && MAKE_QSTRING_THREAD_SAFE extern TQMutex *tqt_sharedStringMutex; diff --git a/src/tools/tqthreadinstance_p.h b/src/tools/tqthreadinstance_p.h new file mode 100644 index 000000000..1cc0d083e --- /dev/null +++ b/src/tools/tqthreadinstance_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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_P_H +#define TQTHREAD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of TQThread and TQThreadStorage. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifdef TQT_THREAD_SUPPORT + +#ifndef QT_H +#include "tqmutex.h" +#include "ntqwindowdefs.h" +#endif // QT_H + +#ifdef Q_OS_UNIX +#include +#endif + +class TQThread; +class TQEventLoop; + +class TQThreadInstance { +public: + static void setCurrentThread(TQThread *thread); + static TQThreadInstance *current(); + + void init(unsigned int stackSize); + void deinit(); + + TQMutex *mutex() const; + void terminate(); + + unsigned int stacksize; + void *args[2]; + void **thread_storage; + bool finished : 1; + bool running : 1; + bool orphan : 1; + +#ifdef Q_OS_UNIX + pthread_cond_t thread_done; + pthread_t thread_id; + + static void *start( void * ); + static void finish( void * ); +#endif // Q_OS_UNIX + +#ifdef Q_OS_WIN32 + TQt::HANDLE handle; + unsigned int thread_id; + int waiters; + + static unsigned int __stdcall start( void * ); + static void finish( TQThreadInstance * ); +#endif // Q_OS_WIN32 + + static void finishGuiThread( TQThreadInstance *d ); + + TQEventLoop* eventLoop; + int cleanupType; + bool disableThreadPostedEvents : 1; +}; + +#endif // TQT_THREAD_SUPPORT +#endif // TQTHREAD_P_H diff --git a/src/tools/tqthreadstorage.h b/src/tools/tqthreadstorage.h new file mode 100644 index 000000000..588621237 --- /dev/null +++ b/src/tools/tqthreadstorage.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQTHREADSTORAGE_H +#define TQTHREADSTORAGE_H + +#ifdef TQT_THREAD_SUPPORT + +#ifndef QT_H +#include "ntqglobal.h" +#endif // QT_H + +class TQ_EXPORT TQThreadStorageData +{ +public: + TQThreadStorageData( void (*func)(void *) ); + ~TQThreadStorageData(); + + void** get() const; + void** set( void* p ); + + static void finish( void** ); + int id; +}; + + +template +class TQThreadStorage +{ +private: + TQThreadStorageData d; + +#if defined(TQ_DISABLE_COPY) + // disable copy constructor and operator= + TQThreadStorage( const TQThreadStorage & ); + TQThreadStorage &operator=( const TQThreadStorage & ); +#endif // TQ_DISABLE_COPY + + static void deleteData( void *x ) { delete (T)x; } + +public: + inline TQThreadStorage() : d( deleteData ) { } + inline ~TQThreadStorage() { } + + inline bool hasLocalData() const + { return d.get() != 0; } + + inline T& localData() + { void **v = d.get(); if ( !v ) v = d.set( 0 ); return *(T*)v; } + + inline T localData() const + { void **v = d.get(); return ( v ? *(T*)v : 0 ); } + + inline void setLocalData( T t ) + { (void) d.set( t ); } +}; + +#endif // TQT_THREAD_SUPPORT + +#endif // TQTHREADSTORAGE_H diff --git a/src/tools/tqthreadstorage_unix.cpp b/src/tools/tqthreadstorage_unix.cpp new file mode 100644 index 000000000..9a7e179b2 --- /dev/null +++ b/src/tools/tqthreadstorage_unix.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 "ntqapplication.h" +#include "tqthread.h" +#include "qplatformdefs.h" + +#include "tqthreadstorage.h" +#include + +#include + +// #define TQTHREADSTORAGE_DEBUG + + +// keep this in sync with the implementation in tqthreadstorage.cpp +static const int MAX_THREAD_STORAGE = 257; // 256 maximum + 1 used in TQRegExp + +static pthread_mutex_t thread_storage_mutex = PTHREAD_MUTEX_INITIALIZER; + +static bool thread_storage_init = FALSE; +static struct { + bool used; + void (*func)( void * ); +} thread_storage_usage[MAX_THREAD_STORAGE]; + + +TQThreadStorageData::TQThreadStorageData( void (*func)( void * ) ) + : id( 0 ) +{ + pthread_mutex_lock( &thread_storage_mutex ); + + // make sure things are initialized + if ( ! thread_storage_init ) + memset( thread_storage_usage, 0, sizeof( thread_storage_usage ) ); + thread_storage_init = TRUE; + + for ( ; id < MAX_THREAD_STORAGE; ++id ) { + if ( !thread_storage_usage[id].used ) + break; + } + + Q_ASSERT( id >= 0 && id < MAX_THREAD_STORAGE ); + thread_storage_usage[id].used = TRUE; + thread_storage_usage[id].func = func; + +#ifdef TQTHREADSTORAGE_DEBUG + tqDebug( "TQThreadStorageData: allocated id %d", id ); +#endif // TQTHREADSTORAGE_DEBUG + + pthread_mutex_unlock( &thread_storage_mutex ); +} + +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; + +#ifdef TQTHREADSTORAGE_DEBUG + tqDebug( "TQThreadStorageData: released id %d", id ); +#endif // TQTHREADSTORAGE_DEBUG + + pthread_mutex_unlock( &thread_storage_mutex ); +} + +void **TQThreadStorageData::get() const +{ + TQThreadInstance *d = TQThreadInstance::current(); + if (!d) { + tqWarning("TQThreadStorage can only be used with threads started with TQThread"); + return 0; + } + TQMutexLocker locker( d->mutex() ); + return d->thread_storage && d->thread_storage[id] ? &d->thread_storage[id] : 0; +} + +void **TQThreadStorageData::set( void *p ) +{ + TQThreadInstance *d = TQThreadInstance::current(); + if (!d) { + tqWarning("TQThreadStorage can only be used with threads started with TQThread"); + return 0; + } + TQMutexLocker locker( d->mutex() ); + if ( !d->thread_storage ) { +#ifdef TQTHREADSTORAGE_DEBUG + tqDebug( "TQThreadStorageData: allocating storage for thread %lx", + (unsigned long) pthread_self() ); +#endif // TQTHREADSTORAGE_DEBUG + + d->thread_storage = new void*[MAX_THREAD_STORAGE]; + memset( d->thread_storage, 0, sizeof( void* ) * MAX_THREAD_STORAGE ); + } + + // delete any previous data + if ( d->thread_storage[id] ) + thread_storage_usage[id].func( d->thread_storage[id] ); + + // store new data + d->thread_storage[id] = p; + return &d->thread_storage[id]; +} + +void TQThreadStorageData::finish( void **thread_storage ) +{ + if ( ! thread_storage ) return; // nothing to do + +#ifdef TQTHREADSTORAGE_DEBUG + tqDebug( "TQThreadStorageData: destroying storage for thread %lx", + (unsigned long) pthread_self() ); +#endif // TQTHREADSTORAGE_DEBUG + + for ( int i = 0; i < MAX_THREAD_STORAGE; ++i ) { + if ( ! thread_storage[i] ) continue; + if ( ! thread_storage_usage[i].used ) { +#ifdef QT_CHECK_STATE + tqWarning( "TQThreadStorage: thread %lx exited after TQThreadStorage destroyed", + (unsigned long) pthread_self() ); +#endif // QT_CHECK_STATE + continue; + } + + thread_storage_usage[i].func( thread_storage[i] ); + } + + delete [] thread_storage; +} + + +/*! + \class TQThreadStorage + \brief The TQThreadStorage class provides per-thread data storage. + + \threadsafe + \ingroup thread + \ingroup environment + + TQThreadStorage is a template class that provides per-thread data + storage. + + \e{Note that due to compiler limitations, TQThreadStorage can only + store pointers.} + + The setLocalData() function stores a single thread-specific value + for the calling thread. The data can be accessed later using the + localData() functions. TQThreadStorage takes ownership of the + data (which must be created on the heap with \e new) and deletes + it when the thread exits (either normally or via termination). + + The hasLocalData() function allows the programmer to determine if + data has previously been set using the setLocalData() function. + This is useful for lazy initializiation. + + For example, the following code uses TQThreadStorage to store a + single cache for each thread that calls the \e cacheObject() and + \e removeFromCache() functions. The cache is automatically + deleted when the calling thread exits (either normally or via + termination). + + \code + TQThreadStorage *> caches; + + void cacheObject( const TQString &key, SomeClass *object ) + { + if ( ! caches.hasLocalData() ) + caches.setLocalData( new TQCache ); + + caches.localData()->insert( key, object ); + } + + void removeFromCache( const TQString &key ) + { + if ( ! caches.hasLocalData() ) + return; // nothing to do + + caches.localData()->remove( key ); + } + \endcode + + \section1 Caveats + + \list + + \i As noted above, TQThreadStorage can only store pointers due to + compiler limitations. Support for value-based objects will be + added when the majority of compilers are able to support partial + template specialization. + + \i The \link ~TQThreadStorage() destructor\endlink does \e not + delete per-thread data. TQThreadStorage only deletes per-thread + data when the thread exits or when setLocalData() is called + multiple times. + + \i TQThreadStorage can only be used with threads started with + TQThread. It \e cannot be used with threads started with + platform-specific APIs. + + \i As a corollary to the above, platform-specific APIs cannot be + used to exit or terminate a TQThread using TQThreadStorage. Doing so + will cause all per-thread data to be leaked. See TQThread::exit() + and TQThread::terminate(). + + \i TQThreadStorage \e can be used to store data for the \e main() + thread \e after TQApplication has been constructed. TQThreadStorage + deletes all data set for the \e main() thread when TQApplication is + destroyed, regardless of whether or not the \e main() thread has + actually finished. + + \i The implementation of TQThreadStorage limits the total number of + TQThreadStorage objects to 256. An unlimited number of threads + can store per-thread data in each TQThreadStorage object. + + \endlist +*/ + +/*! + \fn TQThreadStorage::TQThreadStorage() + + Constructs a new per-thread data storage object. +*/ + +/*! + \fn TQThreadStorage::~TQThreadStorage() + + Destroys the per-thread data storage object. + + Note: The per-thread data stored is \e not deleted. Any data left + in TQThreadStorage is leaked. Make sure that all threads using + TQThreadStorage have exited before deleting the TQThreadStorage. + + \sa hasLocalData() +*/ + +/*! + \fn bool TQThreadStorage::hasLocalData() const + + Returns TRUE if the calling thread has non-zero data available; + otherwise returns FALSE. + + \sa localData() +*/ + +/*! + \fn T& TQThreadStorage::localData() + + Returns a reference to the data that was set by the calling + thread. + + Note: TQThreadStorage can only store pointers. This function + returns a \e reference to the pointer that was set by the calling + thread. The value of this reference is 0 if no data was set by + the calling thread, + + \sa hasLocalData() +*/ +/* + ### addition to the above documentation when we start supporting + ### partial template specialization, and TQThreadStorage can store + ### values *and* pointers + + When using TQThreadStorage to store values (not pointers), this + function stores an object of type \e T (created with its default + constructor) and returns a reference to that object. +*/ + +/*! + \fn const T TQThreadStorage::localData() const + \overload + + Returns a copy of the data that was set by the calling thread. + + Note: TQThreadStorage can only store pointers. This function + returns a pointer to the data that was set by the calling thread. + If no data was set by the calling thread, this function returns 0. + + \sa hasLocalData() +*/ +/* + ### addition to the above documentation when we start supporting + ### partial template specialization, and TQThreadStorage can store + ### values *and* pointers + + When using TQThreadStorage to store values (not pointers), this + function returns an object of type \e T (created with its default + constructor). Unlike the above function, this object is \e not + stored automatically. You will need to call setLocalData() to store + the object. +*/ + +/*! + \fn void TQThreadStorage::setLocalData( T data ) + + Sets the local data for the calling thread to \a data. It can be + accessed later using the localData() functions. + + If \a data is 0, this function deletes the previous data (if + any) and returns immediately. + + If \a data is non-zero, TQThreadStorage takes ownership of the \a + data and deletes it automatically either when the thread exits + (either normally or via termination) or when setLocalData() is + called again. + + Note: TQThreadStorage can only store pointers. The \a data + argument must be either a pointer to an object created on the heap + (i.e. using \e new) or 0. You should not delete \a data + yourself; TQThreadStorage takes ownership and will delete the \a + data itself. + + \sa localData() hasLocalData() +*/ + +#endif // TQT_THREAD_SUPPORT diff --git a/src/tools/tqwaitcondition.h b/src/tools/tqwaitcondition.h new file mode 100644 index 000000000..503d5d6c9 --- /dev/null +++ b/src/tools/tqwaitcondition.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Definition of TQWaitCondition class +** +** Created : 931107 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 TQWAITCONDITION_H +#define TQWAITCONDITION_H + +#ifndef QT_H +#include "ntqglobal.h" +#endif // QT_H + +#if defined(TQT_THREAD_SUPPORT) + +#include + +class TQWaitConditionPrivate; +class TQMutex; + +class TQ_EXPORT TQWaitCondition +{ +public: + TQWaitCondition(); + virtual ~TQWaitCondition(); + + // default argument causes thread to block indefinately + bool wait( unsigned long time = ULONG_MAX ); + bool wait( TQMutex *mutex, unsigned long time = ULONG_MAX ); + + void wakeOne(); + void wakeAll(); + +private: + TQWaitConditionPrivate * d; + +#if defined(TQ_DISABLE_COPY) + TQWaitCondition( const TQWaitCondition & ); + TQWaitCondition &operator=( const TQWaitCondition & ); +#endif +}; + +#endif + +#endif diff --git a/src/tools/tqwaitcondition_unix.cpp b/src/tools/tqwaitcondition_unix.cpp new file mode 100644 index 000000000..78fdb16bc --- /dev/null +++ b/src/tools/tqwaitcondition_unix.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** TQWaitCondition class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools 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 "tqwaitcondition.h" +#include "tqmutex.h" +#include "tqmutex_p.h" + +#include +#include + + +struct TQWaitConditionPrivate { + pthread_cond_t cond; +}; + + +/*! + \class TQWaitCondition tqwaitcondition.h + \threadsafe + \brief The TQWaitCondition class allows waiting/waking for conditions between threads. + + \ingroup thread + \ingroup environment + + TQWaitConditions allow a thread to tell other threads that some + sort of condition has been met; one or many threads can block + waiting for a TQWaitCondition to set a condition with wakeOne() or + wakeAll(). Use wakeOne() to wake one randomly selected event or + wakeAll() to wake them all. For example, say we have three tasks + that should be performed every time the user presses a key; each + task could be split into a thread, each of which would have a + run() body like this: + + \code + TQWaitCondition key_pressed; + + for (;;) { + key_pressed.wait(); // This is a TQWaitCondition global variable + // Key was pressed, do something interesting + do_something(); + } + \endcode + + A fourth thread would read key presses and wake the other three + threads up every time it receives one, like this: + + \code + TQWaitCondition key_pressed; + + for (;;) { + getchar(); + // Causes any thread in key_pressed.wait() to return from + // that method and continue processing + key_pressed.wakeAll(); + } + \endcode + + Note that the order the three threads are woken up in is + undefined, and that if some or all of the threads are still in + do_something() when the key is pressed, they won't be woken up + (since they're not waiting on the condition variable) and so the + task will not be performed for that key press. This can be + avoided by, for example, doing something like this: + + \code + TQMutex mymutex; + TQWaitCondition key_pressed; + int mycount=0; + + // Worker thread code + for (;;) { + key_pressed.wait(); // This is a TQWaitCondition global variable + mymutex.lock(); + mycount++; + mymutex.unlock(); + do_something(); + mymutex.lock(); + mycount--; + mymutex.unlock(); + } + + // Key reading thread code + for (;;) { + getchar(); + mymutex.lock(); + // Sleep until there are no busy worker threads + while( mycount > 0 ) { + mymutex.unlock(); + sleep( 1 ); + mymutex.lock(); + } + mymutex.unlock(); + key_pressed.wakeAll(); + } + \endcode + + The mutexes are necessary because the results of two threads + attempting to change the value of the same variable simultaneously + are unpredictable. +*/ + +/*! + Constructs a new event signalling, i.e. wait condition, object. +*/ +TQWaitCondition::TQWaitCondition() +{ + d = new TQWaitConditionPrivate; + + int ret = pthread_cond_init(&d->cond, NULL); + +#ifdef QT_CHECK_RANGE + if (ret) + tqWarning( "Wait condition init failure: %s", strerror( ret ) ); +#endif +} + + +/*! + Deletes the event signalling, i.e. wait condition, object. +*/ +TQWaitCondition::~TQWaitCondition() +{ + int ret = pthread_cond_destroy(&d->cond); + + if (ret) { +#ifdef QT_CHECK_RANGE + tqWarning( "Wait condition destroy failure: %s", strerror( ret ) ); +#endif + + // seems we have threads waiting on us, lets wake them up + pthread_cond_broadcast(&d->cond); + } + + delete d; +} + +/*! + This wakes one thread waiting on the TQWaitCondition. The thread + that is woken up depends on the operating system's scheduling + policies, and cannot be controlled or predicted. + + \sa wakeAll() +*/ +void TQWaitCondition::wakeOne() +{ + int ret = pthread_cond_signal(&d->cond); + +#ifdef QT_CHECK_RANGE + if (ret) + tqWarning("Wait condition wakeOne failure: %s", strerror(ret)); +#endif +} + +/*! + This wakes all threads waiting on the TQWaitCondition. The order in + which the threads are woken up depends on the operating system's + scheduling policies, and cannot be controlled or predicted. + + \sa wakeOne() +*/ +void TQWaitCondition::wakeAll() +{ + int ret = pthread_cond_broadcast(&d->cond); + +#ifdef QT_CHECK_RANGE + if (ret) + tqWarning("Wait condition wakeAll failure: %s", strerror(ret)); +#endif +} + +/*! + Wait on the thread event object. The thread calling this will + block until either of these conditions is met: + \list + \i Another thread signals it using wakeOne() or wakeAll(). This + function will return TRUE in this case. + \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + default), then the wait will never timeout (the event must be + signalled). This function will return FALSE if the wait timed + out. + \endlist + + \sa wakeOne(), wakeAll() +*/ +bool TQWaitCondition::wait(unsigned long time) +{ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock( &mutex ); + + 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->cond, &mutex, &ti); + } else + ret = pthread_cond_wait(&d->cond, &mutex); + +#ifdef QT_CHECK_RANGE + if (ret && ret != ETIMEDOUT) + tqWarning("Wait condition wait failure: %s",strerror(ret)); +#endif + + pthread_mutex_unlock( &mutex ); + + return (ret == 0); +} + +/*! + \overload + + Release the locked \a mutex and wait on the thread event object. + The \a mutex must be initially locked by the calling thread. If \a + mutex is not in a locked state, this function returns immediately. + If \a mutex is a recursive mutex, this function returns + immediately. The \a mutex will be unlocked, and the calling thread + will block until either of these conditions is met: + \list + \i Another thread signals it using wakeOne() or wakeAll(). This + function will return TRUE in this case. + \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + default), then the wait will never timeout (the event must be + signalled). This function will return FALSE if the wait timed + out. + \endlist + + The mutex will be returned to the same locked state. This function + is provided to allow the atomic transition from the locked state + to the wait state. + + \sa wakeOne(), wakeAll() +*/ +bool TQWaitCondition::wait(TQMutex *mutex, unsigned long time) +{ + if (! mutex) + return FALSE; + + if (mutex->d->type() == Q_MUTEX_RECURSIVE) { +#ifdef QT_CHECK_RANGE + tqWarning("Wait condition warning: using recursive mutexes with\n" + " wait conditions is undefined!"); +#endif + return FALSE; + } + + 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->cond, &mutex->d->handle, &ti); + } else + ret = pthread_cond_wait(&d->cond, &mutex->d->handle); + +#ifdef QT_CHECK_RANGE + if (ret && ret != ETIMEDOUT) + tqWarning("Wait condition wait failure: %s",strerror(ret)); +#endif + + return (ret == 0); +} + +#endif // TQT_THREAD_SUPPORT -- cgit v1.2.3