diff --git a/src/OpenThreads/CMakeLists.txt b/src/OpenThreads/CMakeLists.txt index 91f4ea426..7397e9afd 100644 --- a/src/OpenThreads/CMakeLists.txt +++ b/src/OpenThreads/CMakeLists.txt @@ -77,8 +77,15 @@ IF(CMAKE_SYSTEM MATCHES IRIX) ENDIF() ENDIF(CMAKE_SYSTEM MATCHES IRIX) +# Add support for using Qt threads +IF(QT4_FOUND) + OPTION(BUILD_OPENTHREADS_WITH_QT "Build OpenThreads with Qt threading support." OFF) +ENDIF() + # Maybe we should be using the FindThreads.cmake module? -IF(WIN32) +IF(QT4_FOUND AND BUILD_OPENTHREADS_WITH_QT) + SUBDIRS(qt) +ELSEIF(WIN32) # So I think Cygwin wants to use pthreads IF(CYGWIN) SUBDIRS(pthreads) diff --git a/src/OpenThreads/qt/CMakeLists.txt b/src/OpenThreads/qt/CMakeLists.txt new file mode 100644 index 000000000..2f006c58d --- /dev/null +++ b/src/OpenThreads/qt/CMakeLists.txt @@ -0,0 +1,68 @@ +# This file should only be included when using Qt threads + +SET(LIB_NAME OpenThreads) +SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS}) + +SOURCE_GROUP("Header Files" FILES ${LIB_PUBLIC_HEADERS}) +SET_SOURCE_FILES_PROPERTIES(${LIB_PUBLIC_HEADERS} PROPERTIES HEADER_FILE_ONLY ON) + +SET(QTCLASS_HEADERS + QtThreadPrivateData.h + QtMutexPrivateData.h + QtConditionPrivateData.h + QtBarrierPrivateData.h +) + +# No need to moc headers right now +#QT4_WRAP_CPP( QTCLASS_MOC ${QTCLASS_HEADERS} OPTIONS "-f" ) + +ADD_LIBRARY(${LIB_NAME} + ${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC} + ${LIB_PUBLIC_HEADERS} + ${QTCLASS_HEADERS} + QtThread.cpp + QtMutex.cpp + QtCondition.cpp + QtBarrier.cpp + ../common/Version.cpp + ../common/Atomic.cpp + ${QTCLASS_MOC} + ${OPENTHREADS_VERSIONINFO_RC} +) + +IF(CMAKE_COMPILER_IS_GNUCXX) + # Remove -pedantic flag as it barfs on Qt headers + STRING(REGEX REPLACE "-pedantic" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +ENDIF() + +IF(OPENTHREADS_SONAMES) + SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION}) +ENDIF() + +TARGET_LINK_LIBRARIES(${LIB_NAME} ${QT_QTCORE_LIBRARY}) +INCLUDE_DIRECTORIES(${QT_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}) + +# Since we're building different platforms binaries in +# their respective directories, we need to set the +# link directory so it can find this location. +LINK_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} +) + +IF(MSVC AND OSG_MSVC_VERSIONED_DLL) + HANDLE_MSVC_DLL(ot ${OPENTHREADS_SOVERSION}) +ENDIF() + +INSTALL( + TARGETS OpenThreads + ARCHIVE DESTINATION lib COMPONENT libopenthreads-dev + LIBRARY DESTINATION lib COMPONENT libopenthreads + RUNTIME DESTINATION bin COMPONENT libopenthreads +) +INSTALL( + FILES ${OpenThreads_PUBLIC_HEADERS} + DESTINATION include/OpenThreads + COMPONENT libopenthreads-dev +) + +#commented out# INCLUDE(ModuleInstall OPTIONAL) diff --git a/src/OpenThreads/qt/QtBarrier.cpp b/src/OpenThreads/qt/QtBarrier.cpp new file mode 100644 index 000000000..aea4d566a --- /dev/null +++ b/src/OpenThreads/qt/QtBarrier.cpp @@ -0,0 +1,145 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +// +// QtBarrier.cpp - C++ Barrier class built on top of Qt threads. +// Borrowed from Win32ThreadBarrier.cpp implementation. +// ~~~~~~~~~~~ + +#include "QtBarrierPrivateData.h" +#include +#include +#include +#include + +using namespace OpenThreads; + +//---------------------------------------------------------------------------- +// +// Decription: Constructor +// +// Use: public. +// +Barrier::Barrier(int numThreads) +{ + QtBarrierPrivateData* pd = new QtBarrierPrivateData; + pd->cnt = 0; + pd->phase = 0; + pd->maxcnt = numThreads; + _valid = true; + + _prvData = static_cast(pd); +} + +//---------------------------------------------------------------------------- +// +// Decription: Destructor +// +// Use: public. +// +Barrier::~Barrier() +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + delete pd; + _prvData = 0; +} + +//---------------------------------------------------------------------------- +// +// Description: Reset the barrier to its original state +// +// Use: public. +// +void Barrier::reset() +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + pd->cnt = 0; + pd->phase = 0; +} + +//---------------------------------------------------------------------------- +// +// Description: Block until numThreads threads have entered the barrier. +// +// Use: public. +// +void Barrier::block(unsigned int numThreads) +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + if (numThreads != 0) pd->maxcnt = numThreads; + int my_phase; + + ScopedLock lock(pd->lock); + if ( _valid ) + { + my_phase = pd->phase; + ++pd->cnt; + + if (pd->cnt == pd->maxcnt) + { + pd->cnt = 0; + pd->phase = 1 - my_phase; + pd->cond.broadcast(); + } + else + { + while (pd->phase == my_phase ) + pd->cond.wait(&pd->lock); + } + } +} + +void Barrier::invalidate() +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + pd->lock.lock(); + _valid = false; + + pd->lock.unlock(); + release(); +} + +//---------------------------------------------------------------------------- +// +// Description: Release the barrier, now. +// +// Use: public. +// +void Barrier::release() +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + int my_phase; + + ScopedLock lock(pd->lock); + my_phase = pd->phase; + + pd->cnt = 0; + pd->phase = 1 - my_phase; + pd->cond.broadcast(); +} + +//---------------------------------------------------------------------------- +// +// Description: Return the number of threads currently blocked in the barrier +// +// Use: public +// +int Barrier::numThreadsCurrentlyBlocked() +{ + QtBarrierPrivateData* pd = static_cast(_prvData); + + int numBlocked = -1; + ScopedLock lock(pd->lock); + numBlocked = pd->cnt; + return numBlocked; +} diff --git a/src/OpenThreads/qt/QtBarrierPrivateData.h b/src/OpenThreads/qt/QtBarrierPrivateData.h new file mode 100644 index 000000000..88ee41c69 --- /dev/null +++ b/src/OpenThreads/qt/QtBarrierPrivateData.h @@ -0,0 +1,38 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + + +// +// QtBarrierPrivateData.h - Private data structure for Barrier +// ~~~~~~~~~~~~~~~~~~~~~ + +#ifndef _QTBARRIERPRIVATEDATA_H_ +#define _QTBARRIERPRIVATEDATA_H_ + +#include +#include + +class QtBarrierPrivateData +{ +public: + QtBarrierPrivateData() {} + virtual ~QtBarrierPrivateData() {} + + OpenThreads::Condition cond; // cv for waiters at barrier + OpenThreads::Mutex lock; // mutex for waiters at barrier + volatile int maxcnt; // number of threads to wait for + volatile int cnt; // number of waiting threads + volatile int phase; // flag to seperate two barriers +}; + +#endif diff --git a/src/OpenThreads/qt/QtCondition.cpp b/src/OpenThreads/qt/QtCondition.cpp new file mode 100644 index 000000000..bb80194f6 --- /dev/null +++ b/src/OpenThreads/qt/QtCondition.cpp @@ -0,0 +1,99 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +// +// QtCondition.cpp - C++ Condition class built on top of Qt threads. +// ~~~~~~~~~~~ + +#include "QtMutexPrivateData.h" +#include "QtConditionPrivateData.h" +#include + +using namespace OpenThreads; + +//---------------------------------------------------------------------------- +// +// Decription: Constructor +// +// Use: public. +// +Condition::Condition() +{ + QtConditionPrivateData* pd = new QtConditionPrivateData; + _prvData = static_cast(pd); +} + +//---------------------------------------------------------------------------- +// +// Decription: Destructor +// +// Use: public. +// +Condition::~Condition() +{ + QtConditionPrivateData* pd = static_cast(_prvData); + delete pd; + _prvData = 0; +} + +//---------------------------------------------------------------------------- +// +// Decription: wait on a condition +// +// Use: public. +// +int Condition::wait(Mutex *mutex) +{ + QtMutexPrivateData* mpd = static_cast(mutex->_prvData); + QtConditionPrivateData* pd = static_cast(_prvData); + return pd->wait(mpd) ? 0 : 1; +} + +//---------------------------------------------------------------------------- +// +// Decription: wait on a condition, for a specified period of time +// +// Use: public. +// +int Condition::wait(Mutex *mutex, unsigned long int ms) +{ + QtMutexPrivateData* mpd = static_cast(mutex->_prvData); + QtConditionPrivateData* pd = static_cast(_prvData); + return pd->wait(mpd, ms) ? 0 : 1; +} + +//---------------------------------------------------------------------------- +// +// Decription: signal a thread to wake up. +// +// Use: public. +// +int Condition::signal() +{ + QtConditionPrivateData* pd = static_cast(_prvData); + pd->wakeOne(); + return 0; +} + +//---------------------------------------------------------------------------- +// +// Decription: signal many threads to wake up. +// +// Use: public. +// +int Condition::broadcast() +{ + QtConditionPrivateData* pd = static_cast(_prvData); + pd->wakeAll(); + return 0; +} diff --git a/src/OpenThreads/qt/QtConditionPrivateData.h b/src/OpenThreads/qt/QtConditionPrivateData.h new file mode 100644 index 000000000..b98a44be5 --- /dev/null +++ b/src/OpenThreads/qt/QtConditionPrivateData.h @@ -0,0 +1,32 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + + +// +// QtConditionPrivateData.h - Private data structure for Condition +// ~~~~~~~~~~~~~~~~~~~~~ + +#ifndef _QTCONDITIONPRIVATEDATA_H_ +#define _QTCONDITIONPRIVATEDATA_H_ + +#include +#include + +class QtConditionPrivateData : public QWaitCondition +{ +public: + QtConditionPrivateData() : QWaitCondition() {} + virtual ~QtConditionPrivateData() {} +}; + +#endif diff --git a/src/OpenThreads/qt/QtMutex.cpp b/src/OpenThreads/qt/QtMutex.cpp new file mode 100644 index 000000000..c25a83385 --- /dev/null +++ b/src/OpenThreads/qt/QtMutex.cpp @@ -0,0 +1,88 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +// +// QtMutex.cpp - C++ Mutex class built on top of Qt threads. +// ~~~~~~~~~~~ + +#include "QtMutexPrivateData.h" +#include + +using namespace OpenThreads; + +//---------------------------------------------------------------------------- +// +// Decription: Constructor +// +// Use: public. +// +Mutex::Mutex(MutexType type) +: _mutexType(type) +{ + QMutex::RecursionMode mode = QMutex::NonRecursive; + if (type == MUTEX_RECURSIVE) mode = QMutex::Recursive; + + QtMutexPrivateData* pd = new QtMutexPrivateData(mode); + _prvData = static_cast(pd); +} + +//---------------------------------------------------------------------------- +// +// Decription: Destructor +// +// Use: public. +// +Mutex::~Mutex() +{ + QtMutexPrivateData* pd = static_cast(_prvData); + delete pd; + _prvData = 0; +} + +//---------------------------------------------------------------------------- +// +// Decription: lock the mutex +// +// Use: public. +// +int Mutex::lock() +{ + QtMutexPrivateData* pd = static_cast(_prvData); + pd->lock(); + return 0; +} + +//---------------------------------------------------------------------------- +// +// Decription: unlock the mutex +// +// Use: public. +// +int Mutex::unlock() +{ + QtMutexPrivateData* pd = static_cast(_prvData); + pd->unlock(); + return 0; +} + +//---------------------------------------------------------------------------- +// +// Decription: test if the mutex may be locked +// +// Use: public. +// +int Mutex::trylock() +{ + QtMutexPrivateData* pd = static_cast(_prvData); + return pd->tryLock() ? 0 : 1; +} diff --git a/src/OpenThreads/qt/QtMutexPrivateData.h b/src/OpenThreads/qt/QtMutexPrivateData.h new file mode 100644 index 000000000..4b3b5a3e3 --- /dev/null +++ b/src/OpenThreads/qt/QtMutexPrivateData.h @@ -0,0 +1,32 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + + +// +// QtMutexPrivateData.h - Private data structure for Mutex +// ~~~~~~~~~~~~~~~~~~~~~ + +#ifndef _QTMUTEXPRIVATEDATA_H_ +#define _QTMUTEXPRIVATEDATA_H_ + +#include +#include + +class QtMutexPrivateData : public QMutex +{ +public: + QtMutexPrivateData(RecursionMode mode) : QMutex(mode) {} + virtual ~QtMutexPrivateData() {} +}; + +#endif diff --git a/src/OpenThreads/qt/QtThread.cpp b/src/OpenThreads/qt/QtThread.cpp new file mode 100644 index 000000000..803da0cd3 --- /dev/null +++ b/src/OpenThreads/qt/QtThread.cpp @@ -0,0 +1,463 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +// +// QtThread.cpp - C++ Thread class built on top of Qt threads. +// ~~~~~~~~~~~ + +#include "QtThreadPrivateData.h" +#include +#include + +using namespace OpenThreads; + +//----------------------------------------------------------------------------- +// Initialize thread master priority level +// +Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT; +bool Thread::s_isInitialized = false; + +//---------------------------------------------------------------------------- +// +// Description: Set the concurrency level (no-op) +// +// Use static public +// +int Thread::SetConcurrency(int concurrencyLevel) +{ return -1; } + +//---------------------------------------------------------------------------- +// +// Description: Get the concurrency level +// +// Use static public +// +int Thread::GetConcurrency() +{ return -1; } + +//---------------------------------------------------------------------------- +// +// Decription: Constructor +// +// Use: public. +// +Thread::Thread() +{ + if (!s_isInitialized) Init(); + + QtThreadPrivateData* pd = new QtThreadPrivateData(this); + pd->isRunning = false; + pd->detached = false; + pd->cancelled = false; + pd->cancelMode = 0; + pd->uniqueId = QtThreadPrivateData::createUniqueID(); + pd->cpunum = -1; + pd->stackSize = 0; + pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT; + pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT; + + _prvData = static_cast(pd); +} + +//---------------------------------------------------------------------------- +// +// Description: Destructor +// +// Use: public. +// +Thread::~Thread() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + if (pd->isRunning) + { + std::cout<<"Error: Thread "<< this <<" still running in destructor"<(QThread::currentThread()); + return (pd ? pd->getMasterThread() : 0); +} + +//----------------------------------------------------------------------------- +// +// Description: Initialize Threading +// +// Use: public. +// +void Thread::Init() +{ + s_isInitialized = true; +} + +//----------------------------------------------------------------------------- +// +// Description: Get a unique identifier for this thread. +// +// Use: public +// +int Thread::getThreadId() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + return pd->uniqueId; +} + +//----------------------------------------------------------------------------- +// +// Description: Get the thread's process id +// +// Use: public +// +size_t Thread::getProcessId() +{ + return (size_t)QCoreApplication::applicationPid(); +} + +//----------------------------------------------------------------------------- +// +// Description: Determine if the thread is running +// +// Use: public +// +bool Thread::isRunning() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + return pd->isRunning; +} + +//----------------------------------------------------------------------------- +// +// Description: Start the thread. +// +// Use: public +// +int Thread::start() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->threadStartedBlock.reset(); + + pd->setStackSize( pd->stackSize ); + pd->start(); + + // wait till the thread has actually started. + pd->threadStartedBlock.block(); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Alternate thread start routine. +// +// Use: public +// +int Thread::startThread() +{ + if (_prvData) return start(); + else return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Join the thread. +// +// Use: public +// +int Thread::detach() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->detached = true; + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Join the thread. +// +// Use: public +// +int Thread::join() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + if (pd->detached) return -1; + return pd->wait() ? 0 : -1; +} + +//----------------------------------------------------------------------------- +// +// Description: test the cancel state of the thread. +// +// Use: public +// +int Thread::testCancel() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + if (!pd->cancelled) + return 0; + + if (pd->cancelMode == 2) + return -1; + + if (pd!=QThread::currentThread()) + return -1; + + throw QtThreadCanceled(); +} + +//----------------------------------------------------------------------------- +// +// Description: Cancel the thread. +// +// Use: public +// +int Thread::cancel() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + if (pd->isRunning) + { + if (pd->cancelMode == 2) + return -1; + + pd->cancelled = true; + if (pd->cancelMode == 1) + { + pd->isRunning = false; + pd->terminate(); + } + } + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: set the thread to cancel at the next convenient point. +// +// Use: public +// +int Thread::setCancelModeDeferred() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->cancelMode = 0; + pd->setAsynchronousTermination(false); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: set the thread to cancel immediately +// +// Use: public +// +int Thread::setCancelModeAsynchronous() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->cancelMode = 1; + pd->setAsynchronousTermination(true); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Disable cancelibility +// +// Use: public +// +int Thread::setCancelModeDisable() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->cancelMode = 2; + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Set the thread's schedule priority (if able) +// +// Use: public +// +int Thread::setSchedulePriority(ThreadPriority priority) +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->threadPriority = priority; + + if (pd->isRunning) + pd->applyPriority(); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Get the thread's schedule priority (if able) +// +// Use: public +// +int Thread::getSchedulePriority() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + return pd->threadPriority; +} + +//----------------------------------------------------------------------------- +// +// Description: Set the thread's scheduling policy (if able) +// +// Use: public +// +int Thread::setSchedulePolicy(ThreadPolicy policy) +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->threadPolicy = policy; + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Set the thread's scheduling policy (if able) +// +// Use: public +// +int Thread::getSchedulePolicy() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + return pd->threadPolicy; +} + +//----------------------------------------------------------------------------- +// +// Description: Set the thread's desired stack size +// +// Use: public +// +int Thread::setStackSize(size_t stackSize) +{ + QtThreadPrivateData* pd = static_cast(_prvData); + if (pd->isRunning) return 13; // return EACESS + else pd->stackSize = stackSize; + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Get the thread's stack size. +// +// Use: public +// +size_t Thread::getStackSize() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + return pd->stackSize; +} + +//----------------------------------------------------------------------------- +// +// Description: set processor affinity for the thread +// +// Use: public +// +int Thread::setProcessorAffinity(unsigned int cpunum) +{ + QtThreadPrivateData* pd = static_cast(_prvData); + pd->cpunum = cpunum; + if (!pd->isRunning) return 0; + + // FIXME: + // Qt doesn't have a platform-independent thread affinity method at present. + // Does it automatically configure threads on different processors, or we have to do it ourselves? + return -1; +} + +//----------------------------------------------------------------------------- +// +// Description: Print the thread's scheduling information to stdout. +// +// Use: public +// +void Thread::printSchedulingInfo() +{ + QtThreadPrivateData* pd = static_cast(_prvData); + std::cout << "Thread "<< pd->getMasterThread() <<" priority: "; + + switch (pd->threadPriority) + { + case Thread::THREAD_PRIORITY_MAX: + std::cout << "MAXIMAL" << std::endl; + break; + case Thread::THREAD_PRIORITY_HIGH: + std::cout << "HIGH" << std::endl; + break; + case Thread::THREAD_PRIORITY_DEFAULT: + case Thread::THREAD_PRIORITY_NOMINAL: + std::cout << "NORMAL" << std::endl; + break; + case Thread::THREAD_PRIORITY_LOW: + std::cout << "LOW" << std::endl; + break; + case Thread::THREAD_PRIORITY_MIN: + std::cout << "MINIMAL" << std::endl; + break; + } +} + +//----------------------------------------------------------------------------- +// +// Description: Yield the processor +// +// Use: protected +// +int Thread::YieldCurrentThread() +{ + QThread::yieldCurrentThread(); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: sleep +// +// Use: public +// +int Thread::microSleep(unsigned int microsec) +{ + QtThreadPrivateData::microSleep(microsec); + return 0; +} + +//----------------------------------------------------------------------------- +// +// Description: Get the number of processors +// +int OpenThreads::GetNumberOfProcessors() +{ + return QThread::idealThreadCount(); +} + +//----------------------------------------------------------------------------- +// +// Description: set processor affinity for current thread +// +int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum) +{ + if (cpunum<0) return -1; + + Thread::Init(); + Thread* thread = Thread::CurrentThread(); + if (thread) + return thread->setProcessorAffinity(cpunum); + else + return -1; +} diff --git a/src/OpenThreads/qt/QtThreadPrivateData.h b/src/OpenThreads/qt/QtThreadPrivateData.h new file mode 100644 index 000000000..58188ed1a --- /dev/null +++ b/src/OpenThreads/qt/QtThreadPrivateData.h @@ -0,0 +1,115 @@ +/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + + +// +// QtThreadPrivateData.h - Private data structure for Thread +// ~~~~~~~~~~~~~~~~~~~~~ + +#ifndef _QTTHREADPRIVATEDATA_H_ +#define _QTTHREADPRIVATEDATA_H_ + +#include +#include +#include + +struct QtThreadCanceled {}; + +class QtThreadPrivateData : public QThread +{ +public: + static int createUniqueID() + { + static int nextID = 0; + return nextID++; + } + + static void microSleep(unsigned int microsec) + { + usleep(microsec); + } + + QtThreadPrivateData(OpenThreads::Thread* master) + : QThread(0), _master(master) {} + + virtual ~QtThreadPrivateData() {} + + OpenThreads::Thread* getMasterThread() { return _master; } + + void setAsynchronousTermination( bool enabled ) + { setTerminationEnabled(enabled); } + + void applyPriority() + { + Priority prio = NormalPriority; + switch (threadPriority) + { + case OpenThreads::Thread::THREAD_PRIORITY_MAX: + prio = HighestPriority; + break; + case OpenThreads::Thread::THREAD_PRIORITY_HIGH: + prio = HighPriority; + break; + case OpenThreads::Thread::THREAD_PRIORITY_NOMINAL: + prio = NormalPriority; + break; + case OpenThreads::Thread::THREAD_PRIORITY_LOW: + prio = LowPriority; + break; + case OpenThreads::Thread::THREAD_PRIORITY_MIN: + prio = IdlePriority; + break; + } + setPriority( prio ); + } + + virtual void run() + { + applyPriority(); + isRunning = true; + threadStartedBlock.release(); + + if (_master) + { + try + { + _master->run(); + } + catch (QtThreadCanceled&) + { + try { _master->cancelCleanup(); } + catch (...) {} + } + catch (...) + {} + } + isRunning = false; + } + + OpenThreads::Thread::ThreadPolicy threadPolicy; + OpenThreads::Thread::ThreadPriority threadPriority; + unsigned int stackSize; + int cpunum; + int uniqueId; + int cancelMode; // 0 - deffered; 1 - asynchronous; 2 - disabled + bool cancelled; + bool detached; + bool isRunning; + + OpenThreads::Block threadStartedBlock; + +private: + OpenThreads::Thread* _master; +}; + +#endif