From Wang Rui, QT based OpenThreads implementation

This commit is contained in:
Robert Osfield 2010-10-14 09:31:09 +00:00
parent b55f75111e
commit 82c01cb72e
10 changed files with 1088 additions and 1 deletions

View File

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

View File

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

View File

@ -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 <OpenThreads/Barrier>
#include <OpenThreads/Thread>
#include <OpenThreads/ScopedLock>
#include <iostream>
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<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Barrier::~Barrier()
{
QtBarrierPrivateData* pd = static_cast<QtBarrierPrivateData*>(_prvData);
delete pd;
_prvData = 0;
}
//----------------------------------------------------------------------------
//
// Description: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset()
{
QtBarrierPrivateData* pd = static_cast<QtBarrierPrivateData*>(_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<QtBarrierPrivateData*>(_prvData);
if (numThreads != 0) pd->maxcnt = numThreads;
int my_phase;
ScopedLock<Mutex> 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<QtBarrierPrivateData*>(_prvData);
pd->lock.lock();
_valid = false;
pd->lock.unlock();
release();
}
//----------------------------------------------------------------------------
//
// Description: Release the barrier, now.
//
// Use: public.
//
void Barrier::release()
{
QtBarrierPrivateData* pd = static_cast<QtBarrierPrivateData*>(_prvData);
int my_phase;
ScopedLock<Mutex> 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<QtBarrierPrivateData*>(_prvData);
int numBlocked = -1;
ScopedLock<Mutex> lock(pd->lock);
numBlocked = pd->cnt;
return numBlocked;
}

View File

@ -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 <OpenThreads/Mutex>
#include <OpenThreads/Condition>
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

View File

@ -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 <iostream>
using namespace OpenThreads;
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Condition::Condition()
{
QtConditionPrivateData* pd = new QtConditionPrivateData;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Condition::~Condition()
{
QtConditionPrivateData* pd = static_cast<QtConditionPrivateData*>(_prvData);
delete pd;
_prvData = 0;
}
//----------------------------------------------------------------------------
//
// Decription: wait on a condition
//
// Use: public.
//
int Condition::wait(Mutex *mutex)
{
QtMutexPrivateData* mpd = static_cast<QtMutexPrivateData*>(mutex->_prvData);
QtConditionPrivateData* pd = static_cast<QtConditionPrivateData*>(_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<QtMutexPrivateData*>(mutex->_prvData);
QtConditionPrivateData* pd = static_cast<QtConditionPrivateData*>(_prvData);
return pd->wait(mpd, ms) ? 0 : 1;
}
//----------------------------------------------------------------------------
//
// Decription: signal a thread to wake up.
//
// Use: public.
//
int Condition::signal()
{
QtConditionPrivateData* pd = static_cast<QtConditionPrivateData*>(_prvData);
pd->wakeOne();
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: signal many threads to wake up.
//
// Use: public.
//
int Condition::broadcast()
{
QtConditionPrivateData* pd = static_cast<QtConditionPrivateData*>(_prvData);
pd->wakeAll();
return 0;
}

View File

@ -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 <OpenThreads/Condition>
#include <QtCore/QWaitCondition>
class QtConditionPrivateData : public QWaitCondition
{
public:
QtConditionPrivateData() : QWaitCondition() {}
virtual ~QtConditionPrivateData() {}
};
#endif

View File

@ -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 <iostream>
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<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Mutex::~Mutex()
{
QtMutexPrivateData* pd = static_cast<QtMutexPrivateData*>(_prvData);
delete pd;
_prvData = 0;
}
//----------------------------------------------------------------------------
//
// Decription: lock the mutex
//
// Use: public.
//
int Mutex::lock()
{
QtMutexPrivateData* pd = static_cast<QtMutexPrivateData*>(_prvData);
pd->lock();
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: unlock the mutex
//
// Use: public.
//
int Mutex::unlock()
{
QtMutexPrivateData* pd = static_cast<QtMutexPrivateData*>(_prvData);
pd->unlock();
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: test if the mutex may be locked
//
// Use: public.
//
int Mutex::trylock()
{
QtMutexPrivateData* pd = static_cast<QtMutexPrivateData*>(_prvData);
return pd->tryLock() ? 0 : 1;
}

View File

@ -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 <OpenThreads/Mutex>
#include <QtCore/QMutex>
class QtMutexPrivateData : public QMutex
{
public:
QtMutexPrivateData(RecursionMode mode) : QMutex(mode) {}
virtual ~QtMutexPrivateData() {}
};
#endif

View File

@ -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 <QtCore/QCoreApplication>
#include <iostream>
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<void*>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Thread::~Thread()
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_prvData);
if (pd->isRunning)
{
std::cout<<"Error: Thread "<< this <<" still running in destructor"<<std::endl;
cancel();
}
delete pd;
_prvData = 0;
}
Thread* Thread::CurrentThread()
{
if (!s_isInitialized) Thread::Init();
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(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<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_prvData);
return pd->isRunning;
}
//-----------------------------------------------------------------------------
//
// Description: Start the thread.
//
// Use: public
//
int Thread::start()
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_prvData);
pd->detached = true;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Join the thread.
//
// Use: public
//
int Thread::join()
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_prvData);
pd->cancelMode = 1;
pd->setAsynchronousTermination(true);
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable()
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_prvData);
return pd->threadPriority;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::setSchedulePolicy(ThreadPolicy policy)
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_prvData);
pd->threadPolicy = policy;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::getSchedulePolicy()
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_prvData);
return pd->threadPolicy;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's desired stack size
//
// Use: public
//
int Thread::setStackSize(size_t stackSize)
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_prvData);
return pd->stackSize;
}
//-----------------------------------------------------------------------------
//
// Description: set processor affinity for the thread
//
// Use: public
//
int Thread::setProcessorAffinity(unsigned int cpunum)
{
QtThreadPrivateData* pd = static_cast<QtThreadPrivateData*>(_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<QtThreadPrivateData*>(_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;
}

View File

@ -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 <OpenThreads/Thread>
#include <OpenThreads/Block>
#include <QtCore/QThread>
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