Moved OpenThreads directly into OpenSceneGraph/trunk rather than being introduced via svn:externals.

This change has been done to make it easier for OpenSceneGraph users to check out the svn via https 
without any conflicts introduced with a http externals.
This commit is contained in:
Robert Osfield 2008-04-01 10:49:53 +00:00
parent 73b87274b0
commit 323ce02f23
51 changed files with 7811 additions and 0 deletions

100
include/OpenThreads/Barrier Normal file
View File

@ -0,0 +1,100 @@
/* -*-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.
*/
//
// Barrier - C++ barrier class
// ~~~~~~~
//
#ifndef _OPENTHREADS_BARRIER_
#define _OPENTHREADS_BARRIER_
#include <OpenThreads/Exports>
namespace OpenThreads {
/**
* @class Barrier
* @brief This class provides an object-oriented thread barrier interface
*
* @warning It is unwise to use the construct "Barrier barrier" in the
* global namespace on sgi's. The object "barrier"
* will confilict with the c-library sproc function "barrier" and
* unpredictable results may occur. You have been warned.
*/
class OPENTHREAD_EXPORT_DIRECTIVE Barrier {
public:
/**
* Constructor
*/
Barrier(int numThreads=0);
/**
* Destructor
*/
virtual ~Barrier();
/**
* Reset the barrier to it's original state.
*/
virtual void reset();
/**
* Block until numThreads threads have entered the barrier.
*/
virtual void block(unsigned int numThreads=0);
/**
* Release the barrier, now.
*/
virtual void release();
/**
* Return the number of threads currently blocked in the barrier,
* Return -1 if error.
*/
virtual int numThreadsCurrentlyBlocked();
void invalidate();
private:
/**
* Private copy constructor, to prevent tampering.
*/
Barrier(const Barrier &/*b*/) {};
/**
* Private copy assignment, to prevent tampering.
*/
Barrier &operator=(const Barrier &/*b*/) {return *(this);};
/**
* Implementation-specific private data.
*/
void *_prvData;
bool _valid;
};
}
#endif // !_OPENTHREADS_BARRIER_

177
include/OpenThreads/Block Normal file
View File

@ -0,0 +1,177 @@
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
*
* 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.
*/
#ifndef _OPENTHREADS_BLOCK_
#define _OPENTHREADS_BLOCK_
#include <OpenThreads/Thread>
#include <OpenThreads/Barrier>
#include <OpenThreads/Condition>
#include <OpenThreads/ScopedLock>
namespace OpenThreads {
/** Block is a block that can be used to halt a thread that is waiting another thread to release it.*/
class Block
{
public:
Block():
_released(false) {}
~Block()
{
release();
}
inline bool block()
{
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if( !_released )
{
return _cond.wait(&_mut)==0;
}
else
{
return true;
}
}
inline bool block(unsigned long timeout)
{
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if( !_released )
{
return _cond.wait(&_mut, timeout)==0;
}
else
{
return true;
}
}
inline void release()
{
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (!_released)
{
_released = true;
_cond.broadcast();
}
}
inline void reset()
{
ScopedLock<OpenThreads::Mutex> mutlock(_mut);
_released = false;
}
inline void set(bool doRelease)
{
if (doRelease!=_released)
{
if (doRelease) release();
else reset();
}
}
protected:
Mutex _mut;
Condition _cond;
bool _released;
private:
Block(const Block&) {}
};
/** BlockCount is a block that can be used to halt a thread that is waiting for a specified number of operations to be completed.*/
class BlockCount
{
public:
BlockCount(unsigned int blockCount):
_blockCount(blockCount),
_currentCount(0) {}
~BlockCount()
{
_blockCount = 0;
release();
}
inline void completed()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_currentCount>0)
{
--_currentCount;
if (_currentCount==0)
{
// osg::notify(osg::NOTICE)<<"Released"<<std::endl;
_cond.broadcast();
}
}
}
inline void block()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_currentCount)
_cond.wait(&_mut);
}
inline void reset()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_currentCount!=_blockCount)
{
if (_blockCount==0) _cond.broadcast();
_currentCount = _blockCount;
}
}
inline void release()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_currentCount)
{
_currentCount = 0;
_cond.broadcast();
}
}
inline void setBlockCount(unsigned int blockCount) { _blockCount = blockCount; }
inline unsigned int getBlockCount() const { return _blockCount; }
inline unsigned int getCurrentCount() const { return _currentCount; }
protected:
OpenThreads::Mutex _mut;
OpenThreads::Condition _cond;
unsigned int _blockCount;
unsigned int _currentCount;
private:
BlockCount(const BlockCount&) {}
};
}
#endif

View File

@ -0,0 +1,93 @@
/* -*-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.
*/
//
// Condition - C++ condition class
// ~~~~~~~~~
//
#ifndef _OPENTHREADS_CONDITION_
#define _OPENTHREADS_CONDITION_
#include <OpenThreads/Exports>
#include <OpenThreads/Mutex>
namespace OpenThreads {
/**
* @class Condition
* @brief This class provides an object-oriented thread condition interface.
*/
class OPENTHREAD_EXPORT_DIRECTIVE Condition {
public:
/**
* Constructor
*/
Condition();
/**
* Destructor
*/
virtual ~Condition();
/**
* Wait on a mutex.
*/
virtual int wait(Mutex *mutex);
/**
* Wait on a mutex for a given amount of time (ms)
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int wait(Mutex *mutex, unsigned long int ms);
/**
* Signal a SINGLE thread to wake if it's waiting.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int signal();
/**
* Wake all threads waiting on this condition.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int broadcast();
private:
/**
* Private copy constructor, to prevent tampering.
*/
Condition(const Condition &/*c*/) {};
/**
* Private copy assignment, to prevent tampering.
*/
Condition &operator=(const Condition &/*c*/) {return *(this);};
/**
* Implementation-specific data
*/
void *_prvData;
};
}
#endif // !_OPENTHREADS_CONDITION_

View File

@ -0,0 +1,43 @@
/* -*-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.
*/
#ifndef _OPENTHREAD_EXPORTS_H_
#define _OPENTHREAD_EXPORTS_H_
#ifndef WIN32
#define OPENTHREAD_EXPORT_DIRECTIVE
#else
#if defined( OT_LIBRARY_STATIC )
#define OPENTHREAD_EXPORT_DIRECTIVE
#elif defined( OPENTHREADS_EXPORTS )
#define OPENTHREAD_EXPORT_DIRECTIVE __declspec(dllexport)
#else
#define OPENTHREAD_EXPORT_DIRECTIVE __declspec(dllimport)
#if 0 // Commented out for now
#ifdef _MSC_VER
#ifdef _DEBUG
#pragma comment(lib ,"OpenThreadsWin32d")
#else
#pragma comment(lib, "OpenThreadsWin32")
#endif
#endif
#endif
#endif
#endif
#endif

89
include/OpenThreads/Mutex Normal file
View File

@ -0,0 +1,89 @@
/* -*-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.
*/
//
// Mutex - C++ mutex class
// ~~~~~
//
#ifndef _OPENTHREADS_MUTEX_
#define _OPENTHREADS_MUTEX_
#include <OpenThreads/Exports>
namespace OpenThreads {
/**
* @class Mutex
* @brief This class provides an object-oriented thread mutex interface.
*/
class OPENTHREAD_EXPORT_DIRECTIVE Mutex {
friend class Condition;
public:
/**
* Constructor
*/
Mutex();
/**
* Destructor
*/
virtual ~Mutex();
/**
* Lock the mutex
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int lock();
/**
* Unlock the mutex
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int unlock();
/**
* Test if mutex can be locked.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int trylock();
private:
/**
* Private copy constructor, to prevent tampering.
*/
Mutex(const Mutex &/*m*/) {};
/**
* Private copy assignment, to prevent tampering.
*/
Mutex &operator=(const Mutex &/*m*/) {return *(this);};
/**
* Implementation-specific private data.
*/
void *_prvData;
};
}
#endif // _OPENTHREADS_MUTEX_

View File

@ -0,0 +1,110 @@
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
*
* 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.
*/
#ifndef _OPENTHREADS_READWRITEMUTEX_
#define _OPENTHREADS_READWRITEMUTEX_
#include <OpenThreads/Thread>
#include <OpenThreads/ReentrantMutex>
namespace OpenThreads {
class ReadWriteMutex
{
public:
ReadWriteMutex():
_readCount(0) {}
virtual ~ReadWriteMutex() {}
virtual int readLock()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
int result = 0;
if (_readCount==0)
{
result = _readWriteMutex.lock();
}
++_readCount;
return result;
}
virtual int readUnlock()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
int result = 0;
if (_readCount>0)
{
--_readCount;
if (_readCount==0)
{
result = _readWriteMutex.unlock();
}
}
return result;
}
virtual int writeLock()
{
return _readWriteMutex.lock();
}
virtual int writeUnlock()
{
return _readWriteMutex.unlock();
}
protected:
ReadWriteMutex(const ReadWriteMutex&) {}
ReadWriteMutex& operator = (const ReadWriteMutex&) { return *(this); }
#if 0
ReentrantMutex _readWriteMutex;
ReentrantMutex _readCountMutex;
#else
OpenThreads::Mutex _readWriteMutex;
OpenThreads::Mutex _readCountMutex;
#endif
unsigned int _readCount;
};
class ScopedReadLock
{
public:
ScopedReadLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.readLock(); }
~ScopedReadLock() { _mutex.readUnlock(); }
protected:
ReadWriteMutex& _mutex;
};
class ScopedWriteLock
{
public:
ScopedWriteLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.writeLock(); }
~ScopedWriteLock() { _mutex.writeUnlock(); }
protected:
ReadWriteMutex& _mutex;
};
}
#endif

View File

@ -0,0 +1,125 @@
/* -*-c++-*- OpenThreads - Copyright (C) 1998-2007 Robert Osfield
*
* 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.
*/
#ifndef _OPENTHREADS_REENTRANTMUTEX_
#define _OPENTHREADS_REENTRANTMUTEX_
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>
namespace OpenThreads {
class ReentrantMutex : public OpenThreads::Mutex
{
public:
ReentrantMutex():
_threadHoldingMutex(0),
_lockCount(0) {}
virtual ~ReentrantMutex() {}
virtual int lock()
{
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
++_lockCount;
return 0;
}
else
{
int result = Mutex::lock();
if (result==0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
_threadHoldingMutex = OpenThreads::Thread::CurrentThread();
_lockCount = 1;
}
return result;
}
}
virtual int unlock()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
#if 0
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
{
--_lockCount;
if (_lockCount<=0)
{
_threadHoldingMutex = 0;
return Mutex::unlock();
}
}
else
{
osg::notify(osg::NOTICE)<<"Error: ReentrantMutex::unlock() - unlocking from the wrong thread."<<std::endl;
}
#else
if (_lockCount>0)
{
--_lockCount;
if (_lockCount<=0)
{
_threadHoldingMutex = 0;
return Mutex::unlock();
}
}
#endif
return 0;
}
virtual int trylock()
{
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
++_lockCount;
return 0;
}
else
{
int result = Mutex::trylock();
if (result==0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lockCountMutex);
_threadHoldingMutex = OpenThreads::Thread::CurrentThread();
_lockCount = 1;
}
return result;
}
}
private:
ReentrantMutex(const ReentrantMutex&):OpenThreads::Mutex() {}
ReentrantMutex& operator =(const ReentrantMutex&) { return *(this); }
OpenThreads::Thread* _threadHoldingMutex;
OpenThreads::Mutex _lockCountMutex;
unsigned int _lockCount;
};
}
#endif

View File

@ -0,0 +1,47 @@
/* -*-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.
*/
//
// ScopedLock and ReverseScopedLock templates
// ~~~~~~~
//
#ifndef _ScopedLock_
#define _ScopedLock_
namespace OpenThreads{
template <class M> class ScopedLock
{
private:
M& m_lock;
ScopedLock(const ScopedLock&); // prevent copy
ScopedLock& operator=(const ScopedLock&); // prevent assign
public:
explicit ScopedLock(M& m):m_lock(m) {m_lock.lock();}
~ScopedLock(){m_lock.unlock();}
};
template <class M> class ReverseScopedLock
{
private:
M& m_lock;
ReverseScopedLock(const ReverseScopedLock&); // prevent copy
ReverseScopedLock& operator=(const ReverseScopedLock&); // prevent assign
public:
explicit ReverseScopedLock(M& m):m_lock(m) {m_lock.unlock();}
~ReverseScopedLock(){m_lock.lock();}
};
}
#endif

389
include/OpenThreads/Thread Normal file
View File

@ -0,0 +1,389 @@
/* -*-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.
*/
//
// Thread - C++ Thread class
// ~~~~~~~~
//
#ifndef _OPENTHREADS_THREAD_
#define _OPENTHREADS_THREAD_
#include <sys/types.h>
#include <OpenThreads/Mutex>
namespace OpenThreads {
/**
* Get the number of processors.
*
* Note, systems where no support exists for querrying the number of processors, 1 is returned.
*
*/
extern OPENTHREAD_EXPORT_DIRECTIVE int GetNumberOfProcessors();
/**
* Set the processor affinity of current thread.
*
* Note, systems where no support exists no affinity will be set, and -1 will be returned.
*
*/
extern OPENTHREAD_EXPORT_DIRECTIVE int SetProcessorAffinityOfCurrentThread(unsigned int cpunum);
/**
* @class Thread
* @brief This class provides an object-oriented thread interface.
*/
class OPENTHREAD_EXPORT_DIRECTIVE Thread {
public:
/**
* Set the concurrency level for a running application. This method
* only has effect if the pthreads thread model is being used, and
* then only when that model is many-to-one (eg. irix).
* in other cases it is ignored. The concurrency level is only a
* *hint* as to the number of execution vehicles to use, the actual
* implementation may do anything it wants. Setting the value
* to 0 returns things to their default state.
*
* @return previous concurrency level, -1 indicates no-op.
*/
static int SetConcurrency(int concurrencyLevel);
/**
* Get the concurrency level for a running application. In this
* case, a return code of 0 means that the application is in default
* mode. A return code of -1 means that the application is incapable
* of setting an arbitrary concurrency, because it is a one-to-one
* execution model (sprocs, linuxThreads)
*/
static int GetConcurrency();
/**
* Enumerated Type for thread priority
*/
enum ThreadPriority {
THREAD_PRIORITY_MAX, /**< The maximum possible priority */
THREAD_PRIORITY_HIGH, /**< A high (but not max) setting */
THREAD_PRIORITY_NOMINAL, /**< An average priority */
THREAD_PRIORITY_LOW, /**< A low (but not min) setting */
THREAD_PRIORITY_MIN, /**< The miniumum possible priority */
THREAD_PRIORITY_DEFAULT /**< Priority scheduling default */
};
/**
* Enumerated Type for thread scheduling policy
*/
enum ThreadPolicy {
THREAD_SCHEDULE_FIFO, /**< First in, First out scheduling */
THREAD_SCHEDULE_ROUND_ROBIN, /**< Round-robin scheduling (LINUX_DEFAULT) */
THREAD_SCHEDULE_TIME_SHARE, /**< Time-share scheduling (IRIX DEFAULT) */
THREAD_SCHEDULE_DEFAULT /**< Default scheduling */
};
/**
* Constructor
*/
Thread();
/**
* Destructor
*/
virtual ~Thread();
/**
* Return a pointer to the current running thread
*/
static Thread *CurrentThread();
/**
* Initialize Threading in a program. This method must be called before
* you can do any threading in a program.
*/
static void Init();
/**
* Yield the processor.
*
* @note This method operates on the calling process. And is
* equivalent to calling sched_yield().
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
static int YieldCurrentThread();
/**
* This method will return the ThreadPriority of the master process.
* (ie, the one calling the thread->start() methods for the first time)
* The method will almost certainly return
* Thread::THREAD_PRIORITY_DEFAULT if
* Init() has not been called.
*
* @return the Thread::ThreadPriority of the master thread.
*/
static ThreadPriority GetMasterPriority() {return s_masterThreadPriority;};
/**
* Get a unique thread id. This id is monotonically increasing.
*
* @return a unique thread identifier
*/
int getThreadId();
/**
* Get the thread's process id. This is the pthread_t or pid_t value
* depending on the threading model being used.
*
* @return thread process id.
*/
size_t getProcessId();
/**
* Start the thread. This method will configure the thread, set
* it's priority, and spawn it.
*
* @note if the stack size specified setStackSize is smaller than the
* smallest allowable stack size, the threads stack size will be set to
* the minimum allowed, and may be retrieved via the getStackSize()
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int start();
int startThread();
/**
* Test the cancel state of the thread. If the thread has been canceled
* this method will cause the thread to exit now. This method operates
* on the calling thread.
*
* Returns 0 if normal, -1 if called from a thread other that this.
*/
int testCancel();
/**
* Cancel the thread. Equivalent to SIGKILL.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
virtual int cancel();
/**
* Set the thread's schedule priority. This is a complex method.
* Beware of thread priorities when using a many-to-many kernel
* entity implemenation (such as IRIX pthreads). If one is not carefull
* to manage the thread priorities, a priority inversion deadlock can
* easily occur (Although the OpenThreads::Mutex & OpenThreads::Barrier
* constructs have been designed with this senario in mind). Unless
* you have explicit need to set the schedule pirorites for a given
* task, it is best to leave them alone.
*
* @note some implementations (notably LinuxThreads and IRIX Sprocs)
* only alow you to decrease thread priorities dynamically. Thus,
* a lower priority thread will not allow it's priority to be raised
* on the fly.
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setSchedulePriority(ThreadPriority priority);
/**
* Get the thread's schedule priority (if able)
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int getSchedulePriority();
/**
* Set the thread's scheduling policy (if able)
*
* @note On some implementations (notably IRIX Sprocs & LinuxThreads)
* The policy may prohibit the use of SCHEDULE_ROUND_ROBIN and
* SCHEDULE_FIFO policies - due to their real-time nature, and
* the danger of deadlocking the machine when used as super-user.
* In such cases, the command is a no-op.
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setSchedulePolicy(ThreadPolicy policy);
/**
* Get the thread's policy (if able)
*
* @note seting the environment variable OUTPUT_THREADLIB_SCHEDULING_INFO
* will output scheduling information for each thread to stdout.
*
* @return policy if normal, -1 if errno set, errno code otherwise.
*/
int getSchedulePolicy();
/**
* Set the thread's desired stack size (in bytes).
* This method is an attribute of the thread and must be called
* *before* the start() method is invoked.
*
* @note a return code of 13 (EACESS) means that the thread stack
* size can no longer be changed.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setStackSize(size_t size);
/**
* Get the thread's desired stack size.
*
* @return the thread's stack size. 0 indicates that the stack size
* has either not yet been initialized, or not yet been specified by
* the application.
*/
size_t getStackSize();
/**
* Print the thread's scheduling information to stdout.
*/
void printSchedulingInfo();
/**
* Detach the thread from the calling process.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int detach();
/**
* Join the calling process with the thread
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int join();
/**
* Disable thread cancelation altogether. Thread::cancel() has no effect.
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeDisable();
/**
* Mark the thread to cancel aysncronously on Thread::cancel().
* (May not be available with process-level implementations).
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeAsynchronous();
/**
* Mark the thread to cancel at the earliest convenience on
* Thread::cancel() (This is the default)
*
* @return 0 if normal, -1 if errno set, errno code otherwise.
*/
int setCancelModeDeferred();
/**
* Query the thread's running status
*
* @return true if running, false if not.
*/
bool isRunning();
/**
* Thread's run method. Must be implemented by derived classes.
* This is where the action happens.
*/
virtual void run() = 0;
/**
* Thread's cancel cleanup routine, called upon cancel(), after the
* cancelation has taken place, but before the thread exits completely.
* This method should be used to repair parts of the thread's data
* that may have been damaged by a pre-mature cancel. No-op by default.
*/
virtual void cancelCleanup() {};
void* getImplementation(){ return _prvData; };
/** Thread's processor affinity method. This binds a thread to a
* processor whenever possible. This call must be made before
* start() or startThread() and has no effect after the thread
* has been running. In the pthreads implementation, this is only
* implemented on sgi, through a pthread extension. On other pthread
* platforms this is ignored. Returns 0 on success, implementation's
* error on failure, or -1 if ignored.
*/
int setProcessorAffinity( unsigned int cpunum );
/** microSleep method, equivilant to the posix usleep(microsec).
* This is not strictly thread API but is used
* so often with threads. It's basically UNIX usleep. Parameter is
* number of microseconds we current thread to sleep. Returns 0 on
* succes, non-zero on failure (UNIX errno or GetLastError() will give
* detailed description.
*/
static int microSleep( unsigned int microsec);
private:
/**
* The Private Actions class is allowed to operate on private data.
*/
friend class ThreadPrivateActions;
/**
* Private copy constructor, to prevent tampering.
*/
Thread(const Thread &/*t*/) {};
/**
* Private copy assignment, to prevent tampering.
*/
Thread &operator=(const Thread &/*t*/) {return *(this);};
/**
* Implementation-specific data
*/
void * _prvData;
/**
* Master thread's priority, set by Thread::Init.
*/
static ThreadPriority s_masterThreadPriority;
/**
* Is initialized flag
*/
static bool s_isInitialized;
};
}
#endif // !_OPENTHREADS_THREAD_

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.
*/
#ifndef OPENTHREADS_VERSION
#define OPENTHREADS_VERSION 1
#include <OpenThreads/Exports>
extern "C" {
#define OPENTHREADS_MAJOR_VERSION 2
#define OPENTHREADS_MINOR_VERSION 2
#define OPENTHREADS_PATCH_VERSION 0
#define OPENTHREADS_SOVERSION 9
/** OpenThreadsGetVersion() returns the library version number.
* Numbering convention : OpenThreads-1.0 will return 1.0 from OpenThreadsGetVersion. */
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetVersion();
/** The OpenThreadsGetSOVersion() method returns the OpenSceneGraph soversion number. */
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetSOVersion();
/** The OpenThreadsGetLibraryName() method returns the library name in human-friendly form. */
extern OPENTHREAD_EXPORT_DIRECTIVE const char* OpenThreadsGetLibraryName();
}
#endif

View File

@ -0,0 +1,72 @@
# This is mainly for Windows declspec, but other platforms know
# what to do with it.
ADD_DEFINITIONS(-DOPENTHREADS_EXPORTS)
SET(OPENTHREADS_MAJOR_VERSION 2)
SET(OPENTHREADS_MINOR_VERSION 2)
SET(OPENTHREADS_PATCH_VERSION 0)
SET(OPENTHREADS_SOVERSION 9)
SET(OPENTHREADS_VERSION ${OPENTHREADS_MAJOR_VERSION}.${OPENTHREADS_MINOR_VERSION}.${OPENTHREADS_PATCH_VERSION})
SET(HEADER_PATH ${OpenThreads_SOURCE_DIR}/include/OpenThreads)
SET(OpenThreads_PUBLIC_HEADERS
${HEADER_PATH}/Barrier
${HEADER_PATH}/Block
${HEADER_PATH}/Condition
${HEADER_PATH}/Exports
${HEADER_PATH}/Mutex
${HEADER_PATH}/ReadWriteMutex
${HEADER_PATH}/ReentrantMutex
${HEADER_PATH}/ScopedLock
${HEADER_PATH}/Thread
${HEADER_PATH}/Version
)
# User Options
OPTION(DYNAMIC_OPENTHREADS "Set to ON to build OpenThreads for dynamic linking. Use OFF for static." ON)
IF (DYNAMIC_OPENTHREADS)
SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED")
ELSE (DYNAMIC_OPENTHREADS)
SET(OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC "STATIC")
ENDIF(DYNAMIC_OPENTHREADS)
# Use our modified version of FindThreads.cmake which has Sproc hacks.
FIND_PACKAGE(Threads)
# Do we have sproc?
IF(CMAKE_SYSTEM MATCHES IRIX)
IF(CMAKE_USE_SPROC_INIT)
# In this case, only Sproc exists, so no option.
SET(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS 1)
ELSE(CMAKE_USE_SPROC_INIT)
IF(CMAKE_HAVE_SPROC_H)
OPTION(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS "Set to ON to build OpenThreads against sproc instead of pthreads" OFF)
ENDIF(CMAKE_HAVE_SPROC_H)
ENDIF(CMAKE_USE_SPROC_INIT)
ENDIF(CMAKE_SYSTEM MATCHES IRIX)
# Maybe we should be using the FindThreads.cmake module?
IF(WIN32)
# So I think Cygwin wants to use pthreads
IF(CYGWIN)
SUBDIRS(pthreads)
ELSE(CYGWIN)
# Everybody else including Msys should probably go here
SUBDIRS(win32)
# examples)
ENDIF(CYGWIN)
ELSE(WIN32)
IF(UNIX)
IF(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
SUBDIRS(sproc)
ELSE(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
SUBDIRS(pthreads)
ENDIF(OPENTHREADS_USE_SPROC_INSTEAD_OF_PTHREADS)
ELSE(UNIX)
MESSAGE("Sorry, OpenThreads may not support your platform")
ENDIF(UNIX)
ENDIF(WIN32)

View File

@ -0,0 +1,57 @@
/* -*-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.
*/
#include <OpenThreads/Version>
#include <string>
#include <stdio.h>
/* These functions expect OPENTHREADS_MAJOR_VERSION,
* OPENTHREADS_MINOR_VERSION, OPENTHREADS_PATCH_VERSION, and
* OPENTHREADS_SOVERSION to be defined by the build system.
*/
extern "C" {
const char* OpenThreadsGetVersion()
{
static char OpenThreads_version[256];
static int OpenThreads_version_init = 1;
if (OpenThreads_version_init)
{
sprintf(OpenThreads_version,"%d.%d.%d",OPENTHREADS_MAJOR_VERSION,OPENTHREADS_MINOR_VERSION,OPENTHREADS_PATCH_VERSION);
OpenThreads_version_init = 0;
}
return OpenThreads_version;
}
const char* OpenThreadsGetSOVersion()
{
static char OpenThreads_soversion[32];
static int OpenThreads_soversion_init = 1;
if (OpenThreads_soversion_init)
{
sprintf(OpenThreads_soversion,"%d",OPENTHREADS_SOVERSION);
OpenThreads_soversion_init = 0;
}
return OpenThreads_soversion;
}
const char* OpenThreadsGetLibraryName()
{
return "OpenThreads Library";
}
}

View File

@ -0,0 +1,116 @@
# This file should only be included when using Pthreads
INCLUDE (CheckFunctionExists)
INCLUDE (CheckLibraryExists)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckCXXSourceCompiles)
SET(LIB_NAME OpenThreads)
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})
ADD_LIBRARY(${LIB_NAME}
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
${LIB_PUBLIC_HEADERS}
PThread.c++
PThreadBarrier.c++
PThreadBarrierPrivateData.h
PThreadCondition.c++
PThreadConditionPrivateData.h
PThreadMutex.c++
PThreadMutexPrivateData.h
PThreadPrivateData.h
../common/Version.cpp
)
IF(OPENTHREADS_SONAMES)
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
ENDIF(OPENTHREADS_SONAMES)
SET(CMAKE_REQUIRED_LIBRARIES_SAFE "${CMAKE_REQUIRED_LIBRARIES}")
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}")
CHECK_FUNCTION_EXISTS(pthread_yield HAVE_PTHREAD_YIELD)
IF(HAVE_PTHREAD_YIELD)
ADD_DEFINITIONS(-DHAVE_PTHREAD_YIELD)
ELSE(HAVE_PTHREAD_YIELD)
# sched_yield appears not in libc, pthreads or whatever on some systems
CHECK_FUNCTION_EXISTS(sched_yield HAVE_SCHED_YIELD)
IF(NOT HAVE_SCHED_YIELD)
CHECK_LIBRARY_EXISTS(rt sched_yield "" HAVE_SCHED_YIELD)
IF(HAVE_SCHED_YIELD)
SET(CMAKE_THREAD_LIBS_INIT "${CMAKE_THREAD_LIBS_INIT} -lrt")
ENDIF(HAVE_SCHED_YIELD)
ENDIF(NOT HAVE_SCHED_YIELD)
IF(HAVE_SCHED_YIELD)
ADD_DEFINITIONS(-DHAVE_SCHED_YIELD)
ENDIF(HAVE_SCHED_YIELD)
ENDIF(HAVE_PTHREAD_YIELD)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# need to have that for pthread_setaffinity_np on linux
ADD_DEFINITIONS(-D_GNU_SOURCE)
SET(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
CHECK_FUNCTION_EXISTS(pthread_setconcurrency HAVE_PTHREAD_SETCONCURRENCY)
IF(HAVE_PTHREAD_SETCONCURRENCY)
ADD_DEFINITIONS(-DHAVE_PTHREAD_SETCONCURRENCY)
ENDIF(HAVE_PTHREAD_SETCONCURRENCY)
CHECK_FUNCTION_EXISTS(pthread_getconcurrency HAVE_PTHREAD_GETCONCURRENCY)
IF(HAVE_PTHREAD_GETCONCURRENCY)
ADD_DEFINITIONS(-DHAVE_PTHREAD_GETCONCURRENCY)
ENDIF(HAVE_PTHREAD_GETCONCURRENCY)
CHECK_FUNCTION_EXISTS(pthread_setaffinity_np HAVE_PTHREAD_SETAFFINITY_NP)
IF(HAVE_PTHREAD_SETAFFINITY_NP)
ADD_DEFINITIONS(-DHAVE_PTHREAD_SETAFFINITY_NP)
ELSE(HAVE_PTHREAD_SETAFFINITY_NP)
CHECK_CXX_SOURCE_COMPILES("
#include <sched.h>
int main() {
cpu_set_t cpumask;
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
return 0;
}" HAVE_THREE_PARAM_SCHED_SETAFFINITY)
IF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
ADD_DEFINITIONS(-DHAVE_THREE_PARAM_SCHED_SETAFFINITY)
ELSE(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
CHECK_CXX_SOURCE_COMPILES("
#include <sched.h>
int main() {
cpu_set_t cpumask;
sched_setaffinity( 0, &cpumask );
return 0;
}" HAVE_TWO_PARAM_SCHED_SETAFFINITY)
IF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
ADD_DEFINITIONS(-DHAVE_TWO_PARAM_SCHED_SETAFFINITY)
ENDIF(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
ENDIF(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
ENDIF(HAVE_PTHREAD_SETAFFINITY_NP)
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_SAFE}")
TARGET_LINK_LIBRARIES(${LIB_NAME}
${CMAKE_THREAD_LIBS_INIT}
)
# 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}
)
INSTALL(
TARGETS OpenThreads
ARCHIVE DESTINATION lib${LIB_POSTFIX}
LIBRARY DESTINATION lib${LIB_POSTFIX}
RUNTIME DESTINATION bin
)
INSTALL(
FILES ${OpenThreads_PUBLIC_HEADERS}
DESTINATION include/OpenThreads
)
#commented out# INCLUDE(ModuleInstall OPTIONAL)

View File

@ -0,0 +1,46 @@
TOPDIR = ../.
include $(TOPDIR)/Make/makedefs
C++FILES = \
PThread.c++ \
PThreadMutex.c++ \
PThreadCondition.c++ \
PThreadBarrier.c++ \
$(NULL)
INC += -I$(TOPDIR)/include -I.
ifeq ($(OS),Linux)
DEF += -fPIC -DLinux -DGL_GLEXT_PROTOTYPES
LIBS += -lpthread
endif
ifeq ($(OS),SunOS)
LIBS += -lpthread -lposix4
endif
ifeq ($(OS),IRIX)
LIBS += -lpthread
endif
ifeq ($(OS),Darwin)
LIBS += -lpthread
endif
ifeq ($(OS),CYGWIN)
LIBS += -lpthread
DEF += -DOPENTHREADS_EXPORTS
endif
ifeq ($(OS),MINGW)
LIBS += -lpthread -lwinmm
DEF += -DOPENTHREADS_EXPORTS
endif
TARGET_BASENAME = OpenThreads
LIB = $(LIB_PREFIX)$(TARGET_BASENAME)
ifeq ($(COMPILE_USING_TWO_PARAM_sched_setaffinity),yes)
DEF += -DCOMPILE_USING_TWO_PARAM_sched_setaffinity
endif
include $(TOPDIR)/Make/makerules

View File

@ -0,0 +1,992 @@
/* -*-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.
*/
//
// PThread.c++ - C++ Thread class built on top of posix threads.
// ~~~~~~~~~~~
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#if defined __linux || defined __sun || defined __APPLE__
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/unistd.h>
#endif
#if defined(__sgi)
#include <unistd.h>
#endif
#if defined(__hpux)
#include <sys/mpctl.h>
#endif
#if defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
# include <sched.h>
#endif
#if defined (__FreeBSD__) || defined (__APPLE__) || defined (__MACH__)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#include <OpenThreads/Thread>
#include "PThreadPrivateData.h"
#include <iostream>
using namespace OpenThreads;
extern int errno;
const char *OPENTHREAD_VERSION_STRING = "OpenThreads v1.2preAlpha, Posix Threads (Public Implementation)";
#ifdef DEBUG
# define DPRINTF(arg) printf arg
#else
# define DPRINTF(arg)
#endif
//-----------------------------------------------------------------------------
// Initialize the static unique ids.
//
int PThreadPrivateData::nextId = 0;
//-----------------------------------------------------------------------------
// Initialize thread master priority level
//
Thread::ThreadPriority Thread::s_masterThreadPriority =
Thread::THREAD_PRIORITY_DEFAULT;
bool Thread::s_isInitialized = false;
pthread_key_t PThreadPrivateData::s_tls_key;
struct ThreadCleanupStruct {
OpenThreads::Thread *thread;
volatile bool *runflag;
};
//-----------------------------------------------------------------------------
// This cleanup handler is necessary to ensure that the thread will cleanup
// and set its isRunning flag properly.
//
void thread_cleanup_handler(void *arg) {
ThreadCleanupStruct *tcs = static_cast<ThreadCleanupStruct *>(arg);
tcs->thread->cancelCleanup();
*(tcs->runflag) = false;
}
//-----------------------------------------------------------------------------
// Class to support some static methods necessary for pthread's to work
// correctly.
//
namespace OpenThreads {
class ThreadPrivateActions {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can issue the methods.
//
friend class Thread;
private:
//-------------------------------------------------------------------------
// pthreads standard start routine.
//
static void *StartThread(void *data) {
Thread *thread = static_cast<Thread *>(data);
PThreadPrivateData *pd =
static_cast<PThreadPrivateData *>(thread->_prvData);
if (pd->cpunum>=0)
{
#if defined(__sgi)
pthread_setrunon_np( pd->cpunum );
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
cpu_set_t cpumask;
CPU_ZERO( &cpumask );
CPU_SET( pd->cpunum, &cpumask );
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, &cpumask );
#endif
#endif
}
ThreadCleanupStruct tcs;
tcs.thread = thread;
tcs.runflag = &pd->isRunning;
// Set local storage so that Thread::CurrentThread() can return the right thing
int status = pthread_setspecific(PThreadPrivateData::s_tls_key, thread);
if (status)
{
printf("Error: pthread_setspecific(,) returned error status, status = %d\n",status);
}
pthread_cleanup_push(thread_cleanup_handler, &tcs);
#ifdef ALLOW_PRIORITY_SCHEDULING
//---------------------------------------------------------------------
// Set the proper scheduling priorities
//
SetThreadSchedulingParams(thread);
#endif // ] ALLOW_PRIORITY_SCHEDULING
pd->isRunning = true;
// release the thread that created this thread.
pd->threadStartedBlock.release();
thread->run();
pd->isRunning = false;
pthread_cleanup_pop(0);
return 0;
};
//-------------------------------------------------------------------------
// Print information related to thread schduling parameters.
//
static void PrintThreadSchedulingInfo(Thread *thread) {
#ifdef ALLOW_PRIORITY_SCHEDULING // [
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
int status, my_policy, min_priority, max_priority;
struct sched_param my_param;
status = pthread_getschedparam(thread->getProcessId(),
&my_policy,
&my_param);
if(status != 0) {
printf("THREAD INFO (%d) : Get sched: %s\n",
thread->getProcessId(),
strerror(status));
} else {
printf(
"THREAD INFO (%d) : Thread running at %s / Priority: %d\n",
thread->getProcessId(),
(my_policy == SCHED_FIFO ? "SCHEDULE_FIFO"
: (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN"
: (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER"
: "UNKNOWN"))),
my_param.sched_priority);
max_priority = sched_get_priority_max(my_policy);
min_priority = sched_get_priority_min(my_policy);
printf(
"THREAD INFO (%d) : Max priority: %d, Min priority: %d\n",
thread->getProcessId(),
max_priority, min_priority);
}
} else {
printf(
"THREAD INFO (%d) POSIX Priority scheduling not available\n",
thread->getProcessId());
}
fflush(stdout);
#endif // ] ALLOW_PRIORITY_SCHEDULING
}
//--------------------------------------------------------------------------
// Set thread scheduling parameters. Unfortunately on Linux, there's no
// good way to set this, as pthread_setschedparam is mostly a no-op.
//
static int SetThreadSchedulingParams(Thread *thread) {
int status = 0;
#ifdef ALLOW_PRIORITY_SCHEDULING // [
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
int th_policy;
int max_priority, nominal_priority, min_priority;
sched_param th_param;
pthread_getschedparam(thread->getProcessId(),
&th_policy, &th_param);
#ifndef __linux__
switch(thread->getSchedulePolicy()) {
case Thread::THREAD_SCHEDULE_FIFO:
th_policy = SCHED_FIFO;
break;
case Thread::THREAD_SCHEDULE_ROUND_ROBIN:
th_policy = SCHED_RR;
break;
case Thread::THREAD_SCHEDULE_TIME_SHARE:
th_policy = SCHED_OTHER;
break;
default:
#ifdef __sgi
th_policy = SCHED_RR;
#else
th_policy = SCHED_FIFO;
#endif
break;
};
#else
th_policy = SCHED_OTHER; // Must protect linux from realtime.
#endif
#ifdef __linux__
max_priority = 0;
min_priority = 20;
nominal_priority = (max_priority + min_priority)/2;
#else
max_priority = sched_get_priority_max(th_policy);
min_priority = sched_get_priority_min(th_policy);
nominal_priority = (max_priority + min_priority)/2;
#endif
switch(thread->getSchedulePriority()) {
case Thread::THREAD_PRIORITY_MAX:
th_param.sched_priority = max_priority;
break;
case Thread::THREAD_PRIORITY_HIGH:
th_param.sched_priority = (max_priority + nominal_priority)/2;
break;
case Thread::THREAD_PRIORITY_NOMINAL:
th_param.sched_priority = nominal_priority;
break;
case Thread::THREAD_PRIORITY_LOW:
th_param.sched_priority = (min_priority + nominal_priority)/2;
break;
case Thread::THREAD_PRIORITY_MIN:
th_param.sched_priority = min_priority;
break;
default:
th_param.sched_priority = max_priority;
break;
}
status = pthread_setschedparam(thread->getProcessId(),
th_policy,
&th_param);
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
PrintThreadSchedulingInfo(thread);
}
#endif // ] ALLOW_PRIORITY_SCHEDULING
return status;
};
};
}
//----------------------------------------------------------------------------
//
// Description: Set the concurrency level (no-op)
//
// Use static public
//
int Thread::SetConcurrency(int concurrencyLevel) {
#if defined (HAVE_PTHREAD_SETCONCURRENCY)
return pthread_setconcurrency(concurrencyLevel);
#else
return -1;
#endif
}
//----------------------------------------------------------------------------
//
// Description: Get the concurrency level
//
// Use static public
//
int Thread::GetConcurrency() {
#if defined (HAVE_PTHREAD_GETCONCURRENCY)
return pthread_getconcurrency();
#else
return -1;
#endif
}
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Thread::Thread() {
if(!s_isInitialized) Init();
PThreadPrivateData *pd = new PThreadPrivateData();
pd->stackSize = 0;
pd->stackSizeLocked = false;
pd->idSet = false;
pd->isRunning = false;
pd->isCanceled = false;
pd->uniqueId = pd->nextId;
pd->nextId++;
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
pd->cpunum = -1;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Thread::~Thread()
{
PThreadPrivateData *pd = static_cast<PThreadPrivateData *>(_prvData);
if(pd->isRunning)
{
std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
//---------------------------------------------------------------------
// Kill the thread when it is destructed
//
cancel();
}
delete pd;
_prvData = 0;
}
Thread *Thread::CurrentThread()
{
Thread *thread =
static_cast<Thread *>(pthread_getspecific(PThreadPrivateData::s_tls_key));
return thread;
}
//-----------------------------------------------------------------------------
//
// Description: Initialize Threading
//
// Use: public.
//
void Thread::Init() {
if(s_isInitialized) return;
// Allocate a key to be used to access thread local storage
int status = pthread_key_create(&PThreadPrivateData::s_tls_key, NULL);
if (status)
{
printf("Error: pthread_key_create(,) returned error status, status = %d\n",status);
}
#ifdef ALLOW_PRIORITY_SCHEDULING
//--------------------------------------------------------------------------
// If we've got priority scheduling, set things to nominal.
//
if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING)) {
int max_priority, nominal_priority, min_priority;
int th_policy;
sched_param th_param;
pthread_getschedparam(pthread_self(),
&th_policy, &th_param);
max_priority = sched_get_priority_max(th_policy);
min_priority = sched_get_priority_min(th_policy);
nominal_priority = (max_priority + min_priority)/2;
th_param.sched_priority = nominal_priority;
pthread_setschedparam(pthread_self(),
th_policy,
&th_param);
s_masterThreadPriority = Thread::THREAD_PRIORITY_NOMINAL;
} else {
s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
}
#endif // ] ALLOW_PRIORITY_SCHEDULING
s_isInitialized = true;
}
//-----------------------------------------------------------------------------
//
// Description: Get a unique identifier for this thread.
//
// Use: public
//
int Thread::getThreadId() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pd->uniqueId;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's process id
//
// Use: public
//
size_t Thread::getProcessId() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if(pd->idSet == false) return (size_t)(pthread_self());
return (size_t)(pd->tid);
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's processor affinity
//
// Use: public
//
int Thread::setProcessorAffinity(unsigned int cpunum)
{
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
pd->cpunum = cpunum;
if (pd->cpunum<0) return -1;
#ifdef __sgi
int status;
pthread_attr_t thread_attr;
status = pthread_attr_init( &thread_attr );
if(status != 0) {
return status;
}
status = pthread_attr_setscope( &thread_attr, PTHREAD_SCOPE_BOUND_NP );
return status;
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
if (pd->isRunning && Thread::CurrentThread()==this)
{
cpu_set_t cpumask;
CPU_ZERO( &cpumask );
CPU_SET( pd->cpunum, &cpumask );
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
pthread_setaffinity_np (pthread_self(), sizeof(cpumask), &cpumask);
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, &cpumask );
#endif
}
return -1;
#else
return -1;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Determine if the thread is running
//
// Use: public
//
bool Thread::isRunning() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pd->isRunning;
}
//-----------------------------------------------------------------------------
//
// Description: Start the thread.
//
// Use: public
//
int Thread::start() {
int status;
pthread_attr_t thread_attr;
status = pthread_attr_init( &thread_attr );
if(status != 0) {
return status;
}
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
size_t defaultStackSize;
pthread_attr_getstacksize( &thread_attr, &defaultStackSize);
if(status != 0) {
return status;
}
if(defaultStackSize < pd->stackSize) {
pthread_attr_setstacksize( &thread_attr, pd->stackSize);
if(status != 0) {
return status;
}
}
//-------------------------------------------------------------------------
// Now get what we actually have...
//
pthread_attr_getstacksize( &thread_attr, &defaultStackSize);
if(status != 0) {
return status;
}
pd->stackSize = defaultStackSize;
//-------------------------------------------------------------------------
// Prohibit the stack size from being changed.
//
pd->stackSizeLocked = true;
#ifdef ALLOW_PRIORITY_SCHEDULING
status = pthread_attr_setinheritsched( &thread_attr,
PTHREAD_EXPLICIT_SCHED );
pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
#endif // ] ALLOW_PRIORITY_SCHEDULING
if(status != 0) {
return status;
}
pd->threadStartedBlock.reset();
status = pthread_create(&(pd->tid), &thread_attr,
ThreadPrivateActions::StartThread,
static_cast<void *>(this));
// wait till the thread has actually started.
pd->threadStartedBlock.block();
if(status != 0) {
return status;
}
pd->idSet = true;
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() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pthread_detach(pd->tid);
}
//-----------------------------------------------------------------------------
//
// Description: Join the thread.
//
// Use: public
//
int Thread::join() {
void *threadResult = 0; // Dummy var.
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pthread_join(pd->tid, &threadResult);
}
//-----------------------------------------------------------------------------
//
// Description: test the cancel state of the thread.
//
// Use: public
//
int Thread::testCancel() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if(pthread_self() != pd->tid)
return -1;
pthread_testcancel();
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Cancel the thread.
//
// Use: public
//
int Thread::cancel() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if (pd->isRunning)
{
pd->isCanceled = true;
int status = pthread_cancel(pd->tid);
return status;
}
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable() {
return pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 );
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel immediately
//
// Use: public
//
int Thread::setCancelModeAsynchronous() {
int status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
if(status != 0) return status;
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel at the next convienent point.
//
// Use: public
//
int Thread::setCancelModeDeferred() {
int status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
if(status != 0) return status;
return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's schedule priority (if able)
//
// Use: public
//
int Thread::setSchedulePriority(ThreadPriority priority) {
#ifdef ALLOW_PRIORITY_SCHEDULING
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
pd->threadPriority = priority;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
#else
return -1;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's schedule priority (if able)
//
// Use: public
//
int Thread::getSchedulePriority() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pd->threadPriority;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::setSchedulePolicy(ThreadPolicy policy) {
#ifdef ALLOW_PRIORITY_SCHEDULING
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
pd->threadPolicy = policy;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
#else
return -1;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::getSchedulePolicy() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pd->threadPolicy;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's desired stack size
//
// Use: public
//
int Thread::setStackSize(size_t stackSize) {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
if(pd->stackSizeLocked == true) return 13; // EACESS
pd->stackSize = stackSize;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's stack size.
//
// Use: public
//
size_t Thread::getStackSize() {
PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
return pd->stackSize;
}
//-----------------------------------------------------------------------------
//
// Description: Print the thread's scheduling information to stdout.
//
// Use: public
//
void Thread::printSchedulingInfo() {
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
}
//-----------------------------------------------------------------------------
//
// Description: Yield the processor
//
// Use: protected
//
int Thread::YieldCurrentThread()
{
#if defined(HAVE_PTHREAD_YIELD)
pthread_yield();
return 0;
#elif defined(HAVE_SCHED_YIELD)
return sched_yield();
#else
return -1;
#endif
}
// Description: sleep
//
// Use: public
//
int Thread::microSleep(unsigned int microsec)
{
return ::usleep(microsec);
}
//-----------------------------------------------------------------------------
//
// Description: Get the number of processors
//
int OpenThreads::GetNumberOfProcessors()
{
#if defined(__linux__)
long ret = sysconf(_SC_NPROCESSORS_ONLN);
if (ret == -1)
return 0;
return ret;
#elif defined(__sun__)
long ret = sysconf(_SC_NPROCESSORS_ONLN);
if (ret == -1)
return 0;
return ret;
#elif defined(__sgi)
long ret = sysconf(_SC_NPROC_ONLN);
if (ret == -1)
return 0;
return ret;
#elif defined(__hpux)
int ret = mpctl(MPC_GETNUMSPUS, 0, NULL);
if (ret == -1)
return 0;
return ret;
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
uint64_t num_cpus = 0;
size_t num_cpus_length = sizeof(num_cpus);
#if defined(__FreeBSD__)
sysctlbyname("hw.ncpu", &num_cpus, &num_cpus_length, NULL, 0);
#else
sysctlbyname("hw.activecpu", &num_cpus, &num_cpus_length, NULL, 0);
#endif
return num_cpus;
#else
return 1;
#endif
}
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
{
if (cpunum<0) return -1;
Thread::Init();
Thread* thread = Thread::CurrentThread();
if (thread)
{
return thread->setProcessorAffinity(cpunum);
}
else
{
#if defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
cpu_set_t cpumask;
CPU_ZERO( &cpumask );
CPU_SET( cpunum, &cpumask );
#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
#elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, sizeof(cpumask), &cpumask );
#elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
sched_setaffinity( 0, &cpumask );
#endif
#endif
}
return -1;
}

View File

@ -0,0 +1,242 @@
/* -*-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.
*/
//
// PThreadBarrier.c++ - C++ Barrier class built on top of POSIX threads.
// ~~~~~~~~~~~~~~~~~~
//
#include <stdio.h>
#include <unistd.h>
#include <OpenThreads/Barrier>
#include "PThreadBarrierPrivateData.h"
using namespace OpenThreads;
//----------------------------------------------------------------------------
// This cancel cleanup handler is necessary to ensure that the barrier's
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
// later joins.
//
void barrier_cleanup_handler(void *arg) {
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(arg);
pthread_mutex_unlock(mutex);
}
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Barrier::Barrier(int numThreads) {
PThreadBarrierPrivateData *pd = new PThreadBarrierPrivateData();
pd->cnt = 0;
pd->phase = 0;
pd->maxcnt = numThreads;
_valid = true;
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init( &mutex_attr );
#ifndef __linux__ // (not available until NPTL) [
pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
#endif // ] __linux__
#ifdef ALLOW_PRIORITY_SCHEDULING // [
#ifdef __sun // [
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_NONE);
#endif // ] __sun
//-------------------------------------------------------------------------
// Initialization is a bit tricky, since we have to be able to be aware
// that on many-to-many execution vehicle systems, we may run into
// priority inversion deadlocks if a mutex is shared between threads
// of differing priorities. Systems that do this should provide the
// following protocol attributes to prevent deadlocks. Check at runtime.
//
// PRIO_INHERIT causes any thread locking the mutex to temporarily become
// the same priority as the highest thread also blocked on the mutex.
// Although more expensive, this is the prefered method.
//
// PRIO_PROTECT causes any thread locking the mutex to assume the priority
// specified by setprioceiling. pthread_mutex_lock will fail if
// the priority ceiling is lower than the thread's priority. Therefore,
// the priority ceiling must be set to the max priority in order to
// garantee no deadlocks will occur.
//
#if defined (_POSIX_THREAD_PRIO_INHERIT) || defined (_POSIX_THREAD_PRIO_PROTECT) // [
if(sysconf(_POSIX_THREAD_PRIO_INHERIT)) {
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
} else if (sysconf(_POSIX_THREAD_PRIO_PROTECT)) {
int th_policy;
struct sched_param th_param;
pthread_getschedparam(pthread_self(), &th_policy, &th_param);
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
pthread_mutexattr_setprioceiling(&mutex_attr,
sched_get_priority_max(th_policy));
}
#endif // ] Priority sheduling
#endif // ] ALLOW_PRIORITY_SCHEDULING
pthread_mutex_init(&(pd->lock), &mutex_attr);
pthread_cond_init(&(pd->cond), NULL);
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Barrier::~Barrier() {
PThreadBarrierPrivateData *pd =
static_cast<PThreadBarrierPrivateData*>(_prvData);
pthread_mutex_destroy(&(pd->lock));
pthread_cond_destroy(&(pd->cond));
delete pd;
}
//----------------------------------------------------------------------------
//
// Description: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset() {
PThreadBarrierPrivateData *pd =
static_cast<PThreadBarrierPrivateData*>(_prvData);
pd->cnt = 0;
pd->phase = 0;
}
//----------------------------------------------------------------------------
//
// Description: Block until numThreads threads have entered the barrier.
//
// Use: public.
//
void Barrier::block(unsigned int numThreads) {
PThreadBarrierPrivateData *pd =
static_cast<PThreadBarrierPrivateData*>(_prvData);
if(numThreads != 0) pd->maxcnt = numThreads;
int my_phase;
pthread_mutex_lock(&(pd->lock));
if( _valid )
{
my_phase = pd->phase;
++pd->cnt;
if (pd->cnt == pd->maxcnt) { // I am the last one
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pthread_cond_broadcast(&(pd->cond));
}
while (pd->phase == my_phase) {
pthread_cleanup_push(barrier_cleanup_handler, &(pd->lock));
pthread_cond_wait(&(pd->cond), &(pd->lock));
pthread_cleanup_pop(0);
}
}
pthread_mutex_unlock(&(pd->lock));
}
void Barrier::invalidate()
{
PThreadBarrierPrivateData *pd =
static_cast<PThreadBarrierPrivateData*>(_prvData);
pthread_mutex_lock(&(pd->lock));
_valid = false;
pthread_mutex_unlock(&(pd->lock));
release();
}
//----------------------------------------------------------------------------
//
// Description: Release the barrier, now.
//
// Use: public.
//
void Barrier::release() {
PThreadBarrierPrivateData *pd =
static_cast<PThreadBarrierPrivateData*>(_prvData);
int my_phase;
pthread_mutex_lock(&(pd->lock));
my_phase = pd->phase;
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pthread_cond_broadcast(&(pd->cond));
pthread_mutex_unlock(&(pd->lock));
}
//----------------------------------------------------------------------------
//
// Description: Return the number of threads currently blocked in the barrier
//
// Use: public
//
int Barrier::numThreadsCurrentlyBlocked() {
PThreadBarrierPrivateData *pd = static_cast<PThreadBarrierPrivateData*>(_prvData);
int numBlocked = -1;
pthread_mutex_lock(&(pd->lock));
numBlocked = pd->cnt;
pthread_mutex_unlock(&(pd->lock));
return numBlocked;
}

View File

@ -0,0 +1,52 @@
/* -*-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.
*/
//
// PThreadBarrierPrivateData.h - private data structure for barrier
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _PTHREADBARRIERPRIVATEDATA_H_
#define _PTHREADBARRIERPRIVATEDATA_H_
#include <pthread.h>
#include <OpenThreads/Barrier>
namespace OpenThreads {
class PThreadBarrierPrivateData {
friend class Barrier;
private:
PThreadBarrierPrivateData() {};
virtual ~PThreadBarrierPrivateData() {};
pthread_cond_t cond; // cv for waiters at barrier
pthread_mutex_t 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 //_PTHREADBARRIERPRIVATEDATA_H_

View File

@ -0,0 +1,218 @@
/* -*-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.
*/
//
// PThreadCondition.c++ - C++ Condition class built on top of posix threads.
// ~~~~~~~~~~~~~~~~~~~~
//
#if defined(_MSC_VER) || defined(__MINGW32__)
# include <time.h>
#else
# include <sys/time.h>
#endif
#include <stdio.h>
#include <OpenThreads/Condition>
#include "PThreadConditionPrivateData.h"
#include "PThreadMutexPrivateData.h"
using namespace OpenThreads;
#if defined(_MSC_VER) || defined(__MINGW32__)
int gettimeofday(struct timeval* tp, void* tzp) {
LARGE_INTEGER t;
if(QueryPerformanceCounter(&t)) {
/* hardware supports a performance counter */
static int been_here = 0;
static LARGE_INTEGER f;
if( !been_here )
{
been_here = 1;
QueryPerformanceFrequency(&f);
}
tp->tv_sec = t.QuadPart/f.QuadPart;
tp->tv_usec = ((float)t.QuadPart/f.QuadPart*1000*1000)
- (tp->tv_sec*1000*1000);
} else {
/* hardware doesn't support a performance counter, so get the
time in a more traditional way. */
DWORD t;
t = timeGetTime();
tp->tv_sec = t / 1000;
tp->tv_usec = t % 1000;
}
/* 0 indicates that the call succeeded. */
return 0;
}
#endif
//----------------------------------------------------------------------------
// This cancel cleanup handler is necessary to ensure that the barrier's
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
// later joins.
//
void condition_cleanup_handler(void *arg) {
pthread_mutex_t *mutex = static_cast<pthread_mutex_t *>(arg);
pthread_mutex_unlock(mutex);
}
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Condition::Condition() {
PThreadConditionPrivateData *pd =
new PThreadConditionPrivateData();
int status = pthread_cond_init( &pd->condition, NULL );
if (status)
{
printf("Error: pthread_cond_init(,) returned error status, status = %d\n",status);
}
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Condition::~Condition() {
PThreadConditionPrivateData *pd =
static_cast<PThreadConditionPrivateData *>(_prvData);
int status = pthread_cond_destroy( &pd->condition );
if (status)
{
printf("Error: pthread_cond_destroy(,) returned error status, status = %d\n",status);
}
delete pd;
}
//----------------------------------------------------------------------------
//
// Decription: wait on a condition
//
// Use: public.
//
int Condition::wait(Mutex *mutex) {
PThreadConditionPrivateData *pd =
static_cast<PThreadConditionPrivateData *>(_prvData);
PThreadMutexPrivateData *mpd =
static_cast<PThreadMutexPrivateData *>(mutex->_prvData);
int status;
pthread_cleanup_push(condition_cleanup_handler, &mpd->mutex);
status = pthread_cond_wait( &pd->condition, &mpd->mutex );
pthread_cleanup_pop(0);
return status;
}
//----------------------------------------------------------------------------
//
// Decription: wait on a condition, for a specified period of time
//
// Use: public.
//
int Condition::wait(Mutex *mutex, unsigned long int ms) {
PThreadConditionPrivateData *pd =
static_cast<PThreadConditionPrivateData *>(_prvData);
PThreadMutexPrivateData *mpd =
static_cast<PThreadMutexPrivateData *>(mutex->_prvData);
// wait time is now in ms milliseconds, so need to convert to seconds and nanoseconds for timespec strucuture.
unsigned int sec = ms / 1000;
unsigned int nsec = (ms % 1000) * 1000000;
// add to the current time
struct ::timeval now;
::gettimeofday( &now, 0 );
sec += now.tv_sec;
nsec += now.tv_usec*1000;
// now pass on any overflow from nsec onto seconds.
sec += nsec / 1000000000;
nsec = nsec % 1000000000;
struct timespec abstime;
abstime.tv_sec = sec;
abstime.tv_nsec = nsec;
int status;
pthread_cleanup_push(condition_cleanup_handler, &mpd->mutex);
status = pthread_cond_timedwait( &pd->condition, &mpd->mutex, &abstime );
pthread_cleanup_pop(0);
return status;
}
//----------------------------------------------------------------------------
//
// Decription: signal a thread to wake up.
//
// Use: public.
//
int Condition::signal() {
PThreadConditionPrivateData *pd =
static_cast<PThreadConditionPrivateData *>(_prvData);
return pthread_cond_signal( &pd->condition );
}
//----------------------------------------------------------------------------
//
// Decription: signal many threads to wake up.
//
// Use: public.
//
int Condition::broadcast() {
PThreadConditionPrivateData *pd =
static_cast<PThreadConditionPrivateData *>(_prvData);
return pthread_cond_broadcast( &pd->condition );
}

View File

@ -0,0 +1,44 @@
/* -*-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.
*/
//
// PThreadConditionPrivateData.h - Private data structure for Condition
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _PTHREADCONDITIONPRIVATEDATA_H_
#define _PTHREADCONDITIONPRIVATEDATA_H_
#include <pthread.h>
#include <OpenThreads/Condition>
namespace OpenThreads {
class PThreadConditionPrivateData {
friend class Condition;
private:
PThreadConditionPrivateData() {};
virtual ~PThreadConditionPrivateData() {};
pthread_cond_t condition;
};
}
#endif // !_PTHREADCONDITIONPRIVATEDATA_H_

View File

@ -0,0 +1,154 @@
/* -*-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.
*/
//
// PThreadMutex.c++ - C++ Mutex class built on top of posix threads.
// ~~~~~~~~~~~~~~~~
//
#include <unistd.h>
#include <pthread.h>
#include <OpenThreads/Mutex>
#include "PThreadMutexPrivateData.h"
using namespace OpenThreads;
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Mutex::Mutex() {
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init( &mutex_attr );
PThreadMutexPrivateData *pd = new PThreadMutexPrivateData();
#ifndef __linux__ // (not available until NPTL) [
pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_ERRORCHECK );
#endif // ] __linux__
#ifdef ALLOW_PRIORITY_SCHEDULING // [
#ifdef __sun // [
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_NONE);
#endif // ] __sun
//-------------------------------------------------------------------------
// Initialization is a bit tricky, since we have to be able to be aware
// that on many-to-many execution vehicle systems, we may run into
// priority inversion deadlocks if a mutex is shared between threads
// of differing priorities. Systems that do this should provide the
// following protocol attributes to prevent deadlocks. Check at runtime.
//
// PRIO_INHERIT causes any thread locking the mutex to temporarily become
// the same priority as the highest thread also blocked on the mutex.
// Although more expensive, this is the prefered method.
//
// PRIO_PROTECT causes any thread locking the mutex to assume the priority
// specified by setprioceiling. pthread_mutex_lock will fail if
// the priority ceiling is lower than the thread's priority. Therefore,
// the priority ceiling must be set to the max priority in order to
// garantee no deadlocks will occur.
//
#if defined (_POSIX_THREAD_PRIO_INHERIT) || defined (_POSIX_THREAD_PRIO_PROTECT) // [
if(sysconf(_POSIX_THREAD_PRIO_INHERIT)) {
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
} else if (sysconf(_POSIX_THREAD_PRIO_PROTECT)) {
int th_policy;
struct sched_param th_param;
pthread_getschedparam(pthread_self(), &th_policy, &th_param);
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
pthread_mutexattr_setprioceiling(&mutex_attr,
sched_get_priority_max(th_policy));
}
#endif // ] Priority Scheduling.
#endif // ] ALLOW_PRIORITY_SCHEDULING
pthread_mutex_init(&pd->mutex, &mutex_attr);
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Mutex::~Mutex() {
PThreadMutexPrivateData *pd =
static_cast<PThreadMutexPrivateData*>(_prvData);
pthread_mutex_destroy(&pd->mutex);
delete pd;
}
//----------------------------------------------------------------------------
//
// Decription: lock the mutex
//
// Use: public.
//
int Mutex::lock() {
PThreadMutexPrivateData *pd =
static_cast<PThreadMutexPrivateData*>(_prvData);
return pthread_mutex_lock(&pd->mutex);
}
//----------------------------------------------------------------------------
//
// Decription: unlock the mutex
//
// Use: public.
//
int Mutex::unlock() {
PThreadMutexPrivateData *pd =
static_cast<PThreadMutexPrivateData*>(_prvData);
return pthread_mutex_unlock(&pd->mutex);
}
//----------------------------------------------------------------------------
//
// Decription: test if the mutex may be locked
//
// Use: public.
//
int Mutex::trylock() {
PThreadMutexPrivateData *pd =
static_cast<PThreadMutexPrivateData*>(_prvData);
return pthread_mutex_trylock(&pd->mutex);
}

View File

@ -0,0 +1,47 @@
/* -*-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.
*/
//
// PThreadMutexPrivateData.h - Private data structure for Mutex
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _PTHREADMUTEXPRIVATEDATA_H_
#define _PTHREADMUTEXPRIVATEDATA_H_
#include <pthread.h>
#include <OpenThreads/Mutex>
namespace OpenThreads {
class PThreadMutexPrivateData {
friend class Mutex;
friend class Condition;
private:
PThreadMutexPrivateData() {};
virtual ~PThreadMutexPrivateData() {};
pthread_mutex_t mutex;
};
}
#endif // !_PTHREADMUTEXPRIVATEDATA_H_

View File

@ -0,0 +1,78 @@
/* -*-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.
*/
//
// PThreadPrivateData.h - Private data structure for Thread
// ~~~~~~~~~~~~~~~~~~~~~
#ifndef _PTHREADPRIVATEDATA_H_
#define _PTHREADPRIVATEDATA_H_
#include <pthread.h>
#include <OpenThreads/Thread>
#include <OpenThreads/Block>
namespace OpenThreads {
class PThreadPrivateData {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can use our data.
//
friend class Thread;
//-------------------------------------------------------------------------
// We're friendly to PThreadPrivateActions, so it can get at some
// variables.
//
friend class ThreadPrivateActions;
private:
PThreadPrivateData() {};
virtual ~PThreadPrivateData() {};
volatile unsigned int stackSize;
volatile bool stackSizeLocked;
volatile bool isRunning;
Block threadStartedBlock;
volatile bool isCanceled;
volatile bool idSet;
volatile Thread::ThreadPriority threadPriority;
volatile Thread::ThreadPolicy threadPolicy;
pthread_t tid;
volatile int uniqueId;
volatile int cpunum;
static int nextId;
static pthread_key_t s_tls_key;
};
}
#endif // !_PTHREADPRIVATEDATA_H_

View File

@ -0,0 +1,49 @@
# This file should only be included when using Sproc
SET(LIB_NAME OpenThreads)
SET(LIB_PUBLIC_HEADERS ${OpenThreads_PUBLIC_HEADERS})
ADD_LIBRARY(${LIB_NAME}
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
${LIB_PUBLIC_HEADERS}
SharedArena.c++
SharedArena.h
SprocBarrier.c++
SprocBarrierPrivateData.h
SprocCondition.c++
SprocConditionPrivateData.h
SprocMutex.c++
SprocMutexPrivateData.h
SprocThread.c++
SprocThreadPrivateActions.h
SprocThreadPrivateData.h
../common/Version.cpp
)
IF(OPENTHREADS_SONAMES)
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
ENDIF(OPENTHREADS_SONAMES)
# Do we need to link against anything for Sproc?
#TARGET_LINK_LIBRARIES(${LIB_NAME}
#)
# 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}
)
INSTALL(
TARGETS OpenThreads
ARCHIVE DESTINATION lib${LIB_POSTFIX}
LIBRARY DESTINATION lib${LIB_POSTFIX}
RUNTIME DESTINATION bin
)
INSTALL(
FILES ${OpenThreads_PUBLIC_HEADERS}
DESTINATION include/OpenThreads
)
#commented out# INCLUDE(ModuleInstall OPTIONAL)

View File

@ -0,0 +1,17 @@
TOPDIR = ../.
include $(TOPDIR)/Make/makedefs
C++FILES = \
SprocThread.c++ \
SprocMutex.c++ \
SprocBarrier.c++ \
SprocCondition.c++ \
SharedArena.c++ \
$(NULL)
INC += -I$(TOPDIR)/include -I.
TARGET_BASENAME = OpenThreads
LIB = libOpenThreads
include $(TOPDIR)/Make/makerules

View File

@ -0,0 +1,256 @@
/* -*-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.
*/
//
// SharedArena.c++ - Facilities for creating/destroying shared arenas
// ~~~~~~~~~~~~~~~
#include <unistd.h>
#include <sys/types.h>
#include <poll.h>
#include <bstring.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdlib.h>
#include "SharedArena.h"
using namespace OpenThreads;
#ifdef DEBUG
# define DPRINTF(arg) printf arg
#else
# define DPRINTF(arg)
#endif
#define MAX_PROCS 1024
#define SEMAPHORE_ARENA_SIZE 500000
//----------------------------------------------------------------------------
// Static arena initialization
//
usptr_t *SharedArena::_arena = 0;
int SharedArena::_numLocks = 0;
char *SharedArena::_arenaName = 0;
void SharedArena::initArena() {
_arenaName = tmpnam(0);
DPRINTF(("Creating arena: %s\n", _arenaName));
if (unlink(_arenaName) < 0) {
if (errno != ENOENT) {
perror("unlink");
exit(1);
}
}
if (usconfig(CONF_INITUSERS, MAX_PROCS) < 0) {
perror("usconfig1");
exit(1);
}
#ifdef OT_USESHAREDONLY
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) {
perror("usconfig2");
exit(1);
}
#endif
char *sema_arena_size_string = getenv("OPENTHREADS_SEMAPHORE_ARENA_SIZE");
unsigned long int sema_arena_size;
if(sema_arena_size_string != 0L) {
sema_arena_size = atol(sema_arena_size_string);
} else {
sema_arena_size = SEMAPHORE_ARENA_SIZE;
}
if (usconfig(CONF_INITSIZE,sema_arena_size) < 0) {
perror("usconfig3");
exit(1);
}
if ((_arena = usinit(_arenaName)) == 0) {
perror("usinit");
exit(1);
}
}
void SharedArena::removeArena() {
DPRINTF(("Removing arena: %s\n", _arenaName));
#ifndef OT_USESHAREDONLY
if (unlink(_arenaName) < 0) {
perror("unlink");
exit(1);
}
#endif
}
ulock_t SharedArena::allocLock() {
if(_numLocks == 0) initArena();
assert(_arena != 0);
ulock_t lock;
if ((lock = usnewlock(_arena)) == 0) {
perror("usnewlock");
printf("Num Locks: %d\n", _numLocks);
exit(1);
}
++_numLocks;
return lock;
}
barrier_t *SharedArena::allocBarrier() {
if(_numLocks == 0) initArena();
assert(_arena != 0);
barrier_t *bar;
if ((bar= new_barrier(_arena)) == 0) {
perror("new_barrier");
exit(1);
}
++_numLocks;
return bar;
}
int SharedArena::lock(ulock_t lock) {
return ussetlock(lock);
}
int SharedArena::unlock(ulock_t lock) {
return usunsetlock(lock);
}
int SharedArena::trylock(ulock_t lock) {
return ustestlock(lock);
}
void SharedArena::deleteLock(ulock_t lock) {
assert(_arena != 0);
usfreelock(lock, _arena);
--_numLocks;
if(_numLocks == 0) {
removeArena();
}
}
void SharedArena::initBarrier(barrier_t *b) {
init_barrier(b);
}
void SharedArena::freeBarrier(barrier_t *b) {
assert(_arena != 0);
free_barrier(b);
b = 0;
--_numLocks;
if(_numLocks == 0) {
removeArena();
}
}
void SharedArena::block(barrier_t *b, unsigned int n) {
barrier(b, n);
}
usema_t *SharedArena::allocSema() {
if(_numLocks == 0) initArena();
assert(_arena != 0);
usema_t *sema;
sema = usnewpollsema(_arena, 0);
if(sema == 0) {
perror("usnewpollsema");
printf("NUM SEMAS: %d\n", _numLocks);
exit(1);
}
++_numLocks;
return sema;
}
int SharedArena::getSemaFd(usema_t *sema) {
int returnval;
returnval = usopenpollsema(sema, S_IRWXU | S_IRWXG | S_IRWXO);
if(0 > returnval) {
perror("usopenpollsema");
exit(1);
}
return returnval;
}
int SharedArena::pSema(usema_t *sema) {
return uspsema(sema);
}
int SharedArena::vSema(usema_t *sema) {
return usvsema(sema);
}
int SharedArena::testSema(usema_t *sema) {
return ustestsema(sema);
}
int SharedArena::closeSemaFd(usema_t *sema) {
int returnval;
returnval = usclosepollsema(sema);
if(returnval != 0) {
perror("usclosepollsema");
exit(1);
}
return returnval;
}
int SharedArena::freeSema(usema_t *sema) {
assert(_arena != 0);
usfreepollsema(sema, _arena);
--_numLocks;
if(_numLocks == 0) {
removeArena();
}
return 0;
}
#undef OT_USESHAREDONLY

View File

@ -0,0 +1,87 @@
/* -*-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.
*/
// SharedArena.h - Facilities for creating/destroying shared arenas
// ~~~~~~~~~~~~~
#ifndef _SHAREDARENA_H_
#define _SHAREDARENA_H_
#include <unistd.h>
#include <ulocks.h>
#include <errno.h>
#include <assert.h>
namespace OpenThreads {
#define OT_USESHAREDONLY
class SharedArena {
friend class Mutex;
friend class Barrier;
friend class Condition;
private:
static void initArena();
static void removeArena();
static ulock_t allocLock();
static barrier_t *allocBarrier();
static usema_t *allocSema();
static int getSemaFd(usema_t *sema);
static int pSema(usema_t *sema);
static int vSema(usema_t *sema);
static int testSema(usema_t *sema);
static int closeSemaFd(usema_t *sema);
static int freeSema(usema_t *sema);
static int lock(ulock_t lock);
static int unlock(ulock_t lock);
static int trylock(ulock_t lock);
static void deleteLock(ulock_t lock);
static void initBarrier(barrier_t *b);
static void freeBarrier(barrier_t *b);
static void block(barrier_t *b, unsigned int n);
private:
static usptr_t *_arena;
static int _numLocks;
static char *_arenaName;
};
}
#endif // !_SHAREDARENA_H_

View File

@ -0,0 +1,229 @@
/* -*-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.
*/
//
// SprocBarrier.c++ - C++ Barrier class built on top of IRIX process threads.
// ~~~~~~~~~~~~~~~~
#include <ulocks.h>
#include <OpenThreads/Barrier>
#include "SprocBarrierPrivateData.h"
#include "SharedArena.h"
#include "SprocThreadPrivateActions.h"
#ifndef USE_IRIX_NATIVE_BARRIER
#include <OpenThreads/Condition>
#include <OpenThreads/Mutex>
#endif
#ifdef DEBUG
#define DPRINTF(arg) printf arg; fflush(stdout);
#else
#define DPRINTF(arg)
#endif
using namespace OpenThreads;
//----------------------------------------------------------------------------
// This cancel cleanup handler is necessary to ensure that the barrier's
// mutex gets unlocked on cancel. Otherwise deadlocks could occur with
// later joins.
//
void barrier_cleanup_handler(void *arg) {
DPRINTF(("(SPROC BARRIER) cleanup handler called on pid %d\n", getpid()));
Mutex *mutex = static_cast<Mutex *>(arg);
if(mutex->trylock() == 1)
mutex->unlock();
}
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Barrier::Barrier(int numThreads) {
SprocBarrierPrivateData *pd = new SprocBarrierPrivateData();
#ifdef USE_IRIX_NATIVE_BARRIER
pd->barrier = SharedArena::allocBarrier();
pd->numThreads = numThreads;
#else
pd->cnt = 0;
pd->phase = 0;
pd->maxcnt = numThreads;
#endif
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Barrier::~Barrier() {
SprocBarrierPrivateData *pd =
static_cast<SprocBarrierPrivateData*>(_prvData);
#ifdef USE_IRIX_NATIVE_BARRIER
SharedArena::freeBarrier(pd->barrier);
#endif
delete pd;
}
//----------------------------------------------------------------------------
//
// Decription: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset() {
SprocBarrierPrivateData *pd =
static_cast<SprocBarrierPrivateData*>(_prvData);
#ifdef USE_IRIX_NATIVE_BARRIER
SharedArena::initBarrier(pd->barrier);
#else
pd->cnt = 0;
pd->phase = 0;
#endif
}
//----------------------------------------------------------------------------
//
// Decription: Block until numThreads threads have entered the barrier.
//
// Use: public.
//
void Barrier::block(unsigned int numThreads) {
SprocBarrierPrivateData *pd =
static_cast<SprocBarrierPrivateData*>(_prvData);
#ifdef USE_IRIX_NATIVE_BARRIER
if(numThreads == 0) {
SharedArena::block(pd->barrier, pd->numThreads);
} else {
SharedArena::block(pd->barrier, numThreads);
}
#else
pd->_mutex.lock();
if(numThreads != 0) pd->maxcnt = numThreads;
int my_phase;
my_phase = pd->phase;
++pd->cnt;
DPRINTF(("(SPROC BARRIER %d) block, count=%d, maxThreads=%d, phase=%d\n",
getpid(), pd->cnt, pd->maxcnt, pd->phase));
if(pd->cnt == pd->maxcnt) { // I am the last one
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->_cond.broadcast();
}
while (pd->phase == my_phase) {
ThreadPrivateActions::PushCancelFunction(barrier_cleanup_handler,
&pd->_mutex);
pd->_cond.wait(&pd->_mutex);
ThreadPrivateActions::PopCancelFunction();
}
pd->_mutex.unlock();
#endif
}
//----------------------------------------------------------------------------
//
// Description: Release the barrier, now.
//
// Use: public.
//
void Barrier::release() {
SprocBarrierPrivateData *pd =
static_cast<SprocBarrierPrivateData*>(_prvData);
#ifdef USE_IRIX_NATIVE_BARRIER
printf("ERROR >>>>> Barrier::release() cannot be implemented using native IRIX Barriers !!!\n");
#else
int my_phase;
pd->_mutex.lock();
my_phase = pd->phase;
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->_cond.broadcast();
pd->_mutex.unlock();
#endif
}
//----------------------------------------------------------------------------
//
// Description: Return the number of threads currently blocked in the barrier
//
// Use: public
//
int Barrier::numThreadsCurrentlyBlocked() {
SprocBarrierPrivateData *pd =
static_cast<SprocBarrierPrivateData*>(_prvData);
int numBlocked = -1;
pd->_mutex.lock();
numBlocked = pd->cnt;
pd->_cond.broadcast();
return numBlocked;
}

View File

@ -0,0 +1,67 @@
/* -*-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.
*/
// SprocBarrierPrivateData.h - private data structure for barrier
// ~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef _SPROCBARRIERPRIVATEDATA_H_
#define _SPROCBARRIERPRIVATEDATA_H_
#include <ulocks.h>
#include <OpenThreads/Barrier>
#ifndef USE_IRIX_NATIVE_BARRIER
#include <OpenThreads/Condition>
#include <OpenThreads/Mutex>
#endif
namespace OpenThreads {
class SprocBarrierPrivateData {
friend class Barrier;
private:
SprocBarrierPrivateData() {};
virtual ~SprocBarrierPrivateData() {};
#ifdef USE_IRIX_NATIVE_BARRIER
barrier_t *barrier;
unsigned int numThreads;
#else
OpenThreads::Condition _cond;
OpenThreads::Mutex _mutex;
volatile int maxcnt;
volatile int cnt;
volatile int phase;
#endif
};
}
#endif //_SPROCBARRIERPRIVATEDATA_H_

View File

@ -0,0 +1,306 @@
/* -*-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.
*/
//
// SprocCondition.c++ - C++ Condition class built on sprocs.
// ~~~~~~~~~~~~~~~~~~
#include <OpenThreads/Condition>
#include "SprocConditionPrivateData.h"
#include <OpenThreads/Mutex>
#include "SharedArena.h"
#include "SprocThreadPrivateActions.h"
#include <errno.h>
#include <signal.h>
using namespace OpenThreads;
#ifdef DEBUG
#define DPRINTF(arg) printf arg; fflush(stdout);
#define DPRINTLIST(arg) ConditionDebug::printList arg; fflush(stdout);
namespace OpenThreads {
class ConditionDebug {
friend class Condition;
private:
static void printList(std::list<pid_t> &pid_list) {
std::list<pid_t>::iterator iter;
int counter = 0;
printf("(SPROC CONDITION %d) ", getpid());
for(iter=pid_list.begin(); iter!=pid_list.end();++iter) {
printf("Pid [%d]=%d, ", counter, *iter);
++counter;
}
printf("\b\n");
}
};
}
#else
#define DPRINTF(arg)
#define DPRINTLIST(arg)
#endif
void condition_alarm_handler(int signal) {
//DPRINTF(("(SPROC CONDITION) signal alarm handler called.\n"));
sigset(SIGALRM, SIG_DFL);
unblockproc(getpid());
}
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Condition::Condition() {
SprocConditionPrivateData *pd =
new SprocConditionPrivateData();
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Condition::~Condition() {
SprocConditionPrivateData *pd =
static_cast<SprocConditionPrivateData *>(_prvData);
pd->mutex.lock();
DPRINTF(("(SPROC CONDITION) : In destructor\n"));
DPRINTLIST((pd->pid_list));
//-------------------------------------------------------------------------
// Destroy all remaining in the linked-list of waiters (pids).
//
pd->pid_list.clear();
delete pd;
_prvData = 0;
}
//----------------------------------------------------------------------------
//
// Decription: wait on a condition
//
// Use: public.
//
int Condition::wait(Mutex *mutex) {
return wait(mutex, 0);
}
//----------------------------------------------------------------------------
//
// Decription: wait on a condition
//
// Use: public.
//
int Condition::wait(Mutex *mutex, unsigned long int ms) {
unsigned int sec;
unsigned int usec;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
pid_t mypid = getpid();
SprocConditionPrivateData *pd =
static_cast<SprocConditionPrivateData *>(_prvData);
if(ms != 0) {
// Wait for ms milliseconds
sec = ms / 1000;
usec = (ms % 1000) * 1000;
tv.tv_sec = sec;
tv.tv_usec = usec;
DPRINTF(("(SPROC CONDITION) : PID %d timeout values [%d | %d]\n",
mypid, tv.tv_sec, tv.tv_usec));
}
pd->mutex.lock();
pd->pid_list.push_front(mypid);
pd->mutex.unlock();
DPRINTF(("(SPROC CONDITION) : PID %d going to blockproc\n",
mypid));
int status = 0;
status = setblockproccnt(mypid, 0);
// If we're doing a timout, setup the signal handler to deal with it.
if(tv.tv_sec != 0 || tv.tv_usec != 0) {
DPRINTF(("(SPROC CONDITION) : PID %d setting timeout condition\n",
mypid));
sigset(SIGALRM, condition_alarm_handler);
struct timeval recur;
recur.tv_sec = 0;
recur.tv_usec = 0;
itimerval itv;
itv.it_interval = recur;
itv.it_value = tv;
setitimer(ITIMER_REAL, &itv, NULL);
}
mutex->unlock();
ThreadPrivateActions::ThreadCancelTest();
status = blockproc(mypid);
ThreadPrivateActions::ThreadCancelTest();
mutex->lock();
DPRINTF(("(SPROC CONDITION) : PID %d, returned from blockproc %d\n",
mypid, status));
//-------------------------------------------------------------------------
// Pull the pid from the list
//
pd->mutex.lock();
DPRINTLIST((pd->pid_list));
#ifndef DEBUG
// KLUDGE - can optimized this by just doing -remove()-
std::list<pid_t>::iterator iter;
iter = pd->pid_list.begin();
while(iter != pd->pid_list.end()) {
if(*iter == mypid) {
DPRINTF(("(SPROC CONDITION) : PID %d removed itself from the list\n",
mypid));
pd->pid_list.remove(mypid);
iter = pd->pid_list.begin();
} else {
++iter;
}
}
#else
pd->pid_list.remove(mypid);
#endif
DPRINTLIST((pd->pid_list));
pd->mutex.unlock();
if(status == -1) {
return status;
}
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: signal a thread to wake up.
//
// Use: public.
//
int Condition::signal() {
ThreadPrivateActions::ThreadCancelTest();
SprocConditionPrivateData *pd =
static_cast<SprocConditionPrivateData *>(_prvData);
pd->mutex.lock();
if(pd->pid_list.empty()) {
DPRINTF(("(SPROC CONDITION) : No threads to signal\n"));
pd->mutex.unlock(); // Remember to release the mutex.
return 0;
}
//-------------------------------------------------------------------------
// Perform an unblockproc on the first pid in the list.
//
DPRINTF(("(SPROC CONDITION) : PID %d signaling pid %d\n",
getpid(), pd->pid_list.front()));
int status = unblockproc(pd->pid_list.front());
pd->mutex.unlock();
return status;
}
//----------------------------------------------------------------------------
//
// Decription: signal all threads to wake up.
//
// Use: public.
//
int Condition::broadcast() {
ThreadPrivateActions::ThreadCancelTest();
SprocConditionPrivateData *pd =
static_cast<SprocConditionPrivateData *>(_prvData);
pd->mutex.lock();
std::list<pid_t>::iterator iter;
for(iter = pd->pid_list.begin();
iter != pd->pid_list.end();
++iter) {
DPRINTF(("(SPROC CONDITION) Broadcast to pid[%d]\n", *iter));
unblockproc(*iter);
}
pd->mutex.unlock();
return 0;
}

View File

@ -0,0 +1,82 @@
/* -*-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.
*/
//
// SprocConditionPrivateData.h - Private data structure for Condition
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef _SPROCCONDITIONPRIVATEDATA_H_
#define _SPROCCONDITIONPRIVATEDATA_H_
#include <unistd.h>
#include <sys/types.h>
#include <bstring.h>
#include <sys/time.h>
#include <ulocks.h>
#include <list>
#include <OpenThreads/Mutex>
#include <OpenThreads/Condition>
namespace OpenThreads {
class SemaLink {
friend class SprocConditionPrivatedata;
friend class Condition;
friend class ConditionDebug;
private:
SemaLink() {};
virtual ~SemaLink() {};
SemaLink *next;
usema_t *sema;
int select_cond; // 0=pre-select, 1=in-select, 2=post-select
};
class SprocConditionPrivateData {
friend class Condition;
private:
SprocConditionPrivateData() {
pid_list.clear();
};
virtual ~SprocConditionPrivateData() {
pid_list.clear();
};
std::list<pid_t> pid_list;
Mutex mutex;
};
}
#endif // !_SPROCCONDITIONPRIVATEDATA_H_

View File

@ -0,0 +1,126 @@
/* -*-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.
*/
//
// SprocMutex.c++ - C++ Mutex class built on top of posix threads.
// ~~~~~~~~~~~~~~
#include <unistd.h>
#include <ulocks.h>
#include <errno.h>
#include <assert.h>
#include <OpenThreads/Mutex>
#include "SharedArena.h"
#include "SprocMutexPrivateData.h"
#include "SprocThreadPrivateActions.h"
using namespace OpenThreads;
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Mutex::Mutex() {
SprocMutexPrivateData *pd = new SprocMutexPrivateData();
pd->mutex = SharedArena::allocLock();
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Mutex::~Mutex() {
SprocMutexPrivateData *pd =
static_cast<SprocMutexPrivateData*>(_prvData);
SharedArena::deleteLock(pd->mutex);
delete pd;
}
//----------------------------------------------------------------------------
//
// Decription: lock the mutex
//
// Use: public.
//
int Mutex::lock() {
ThreadPrivateActions::ThreadCancelTest();
SprocMutexPrivateData *pd =
static_cast<SprocMutexPrivateData*>(_prvData);
int status = SharedArena::lock(pd->mutex);
if(status == -1) {
return status;
}
if(status == 1) {
return 0;
} else {
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: unlock the mutex
//
// Use: public.
//
int Mutex::unlock() {
SprocMutexPrivateData *pd =
static_cast<SprocMutexPrivateData*>(_prvData);
int status = SharedArena::unlock(pd->mutex);
ThreadPrivateActions::ThreadCancelTest();
return status;
}
//----------------------------------------------------------------------------
//
// Decription: test if the mutex may be locked
//
// Use: public.
//
int Mutex::trylock() {
SprocMutexPrivateData *pd =
static_cast<SprocMutexPrivateData*>(_prvData);
int status = SharedArena::trylock(pd->mutex);
return status;
}

View File

@ -0,0 +1,45 @@
/* -*-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.
*/
//
// SprocMutexPrivateData.h - Private data structure for Mutex
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef _SPROCMUTEXPRIVATEDATA_H_
#define _SPROCMUTEXPRIVATEDATA_H_
#include <ulocks.h>
#include <OpenThreads/Mutex>
namespace OpenThreads {
class SprocMutexPrivateData {
friend class SprocThreadPrivateActions;
friend class Mutex;
private:
SprocMutexPrivateData() {};
virtual ~SprocMutexPrivateData() {};
ulock_t mutex;
};
}
#endif // _SPROCMUTEXPRIVATEDATA_H_

View File

@ -0,0 +1,823 @@
/* -*-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.
*/
//
// SprocThread.c++ - C++ Thread class built on top of IRIX sproc.
// ~~~~~~~~~~~~~~~
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/sysmp.h>
#include <signal.h>
#include <unistd.h>
#include <list>
#include <OpenThreads/Thread>
#include "SprocMutexPrivateData.h"
#include "SprocThreadPrivateData.h"
#include "SprocThreadPrivateActions.h"
using namespace OpenThreads;
extern int errno;
const char *OPENTHREAD_VERSION_STRING = "Sproc Thread Model, v1.1 ("__DATE__" "__TIME__")";
#ifdef DEBUG
#define DPRINTF(arg) printf arg; fflush(stdout);
#else
#define DPRINTF(ARG)
#endif
static void sproc_dead_child_sig_handler(int sigid);
//-----------------------------------------------------------------------------
// Initialize the static unique ids.
//
int SprocThreadPrivateData::nextId = 0;
//-----------------------------------------------------------------------------
// Initialize thread master priority level
//
Thread::ThreadPriority Thread::s_masterThreadPriority =
Thread::THREAD_PRIORITY_MAX;
bool Thread::s_isInitialized = false;
std::list<Thread *> ThreadPrivateActions::s_threadList;
void ThreadPrivateActions::ThreadCancelTest() {
OpenThreads::Thread *t = GetThread(getpid());
if(t != 0L) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(t->_prvData);
bool *dieflag = GetDeathFlag(t);
if(*dieflag==false) return;
DPRINTF(("(SPROC THREAD) Thread Cancel Test Passed for %d\n",
getpid()));
if(!pd->cancelFuncStack.empty())
pd->cancelFuncStack.top().routine(pd->cancelFuncStack.top().arg);
t->cancelCleanup();
pd->isRunning = false;
exit(1);
}
}
bool *ThreadPrivateActions::GetDeathFlag(Thread *thread) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(thread->_prvData);
return (bool *)(&(pd->dieFlag));
}
Thread *ThreadPrivateActions::GetThread(pid_t thread_id) {
std::list<Thread *>::iterator iter;
for(iter = s_threadList.begin();
iter != s_threadList.end();
++iter) {
Thread *t = *iter;
if(t->getProcessId() == thread_id) return t;
}
return 0L; // no thread found;
};
void ThreadPrivateActions::ThreadCancelHandler(int sigid) {
Thread *t = GetThread(getpid());
if(t != 0L) {
bool * dieflag = GetDeathFlag(t);
*dieflag = true;
sigset(SIGINT, SIG_DFL);
unblockproc(getpid());
}
}
//-------------------------------------------------------------------------
// standard start routine.
//
void ThreadPrivateActions::StartThread(void *data)
{
Thread *thread = static_cast<Thread *>(data);
if (thread->_prvData==0) return;
AddThread(thread);
*((Thread **)&PRDA->usr_prda) = (Thread *)thread;
SetThreadSchedulingParams(thread);
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(thread->_prvData);
sigset(SIGINT, ThreadCancelHandler);
size_t defaultStackSize;
prctl(PR_GETSTACKSIZE, &defaultStackSize);
if(defaultStackSize < pd->stackSize) {
prctl(PR_SETSTACKSIZE, pd->stackSize);
}
prctl(PR_GETSTACKSIZE, &pd->stackSize);
pd->stackSizeLocked = true;
pd->isRunning = true;
// release the thread that created this thread.
pd->threadStartedBlock.release();
thread->run();
pd->isRunning = false;
RemoveThread(thread);
if(pd->detached == true ) {
exit(0);
}
return;
};
void ThreadPrivateActions::AddThread(Thread *thread) {
s_threadList.push_front(thread);
};
void ThreadPrivateActions::RemoveThread(Thread *thread) {
s_threadList.remove(thread);
};
void ThreadPrivateActions::PrintThreadSchedulingInfo(Thread *thread) {
int status, my_policy, min_priority, max_priority;
struct sched_param my_param;
status = sched_getparam(thread->getProcessId(),
&my_param);
my_policy = sched_getscheduler(thread->getProcessId());
if(status != 0 || my_policy == -1) {
printf("THREAD INFO (%d) : Get sched param: %s/%s\n",
thread->getProcessId(),
strerror(status),
strerror(errno));
} else {
printf(
"THREAD INFO (%d) : Thread running at %s / Priority: %d\n",
thread->getProcessId(),
(my_policy == SCHED_FIFO ? "SCHEDULE_FIFO"
: (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN"
: (my_policy == SCHED_TS ? "SCHEDULE_TIME_SHARE"
: (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER"
: "UNKNOWN")))),
my_param.sched_priority);
max_priority = sched_get_priority_max(my_policy);
min_priority = sched_get_priority_min(my_policy);
printf(
"THREAD INFO (%d) : Max priority: %d, Min priority: %d\n",
thread->getProcessId(),
max_priority, min_priority);
}
}
int ThreadPrivateActions::SetThreadSchedulingParams(Thread *thread) {
int status;
int th_priority;
int max_priority, nominal_priority, min_priority;
max_priority = 0; // This is as high as we can regularly go.
min_priority = 20;
nominal_priority = (max_priority + min_priority)/2;
switch(thread->getSchedulePriority()) {
case Thread::THREAD_PRIORITY_MAX:
th_priority = max_priority;
break;
case Thread::THREAD_PRIORITY_HIGH:
th_priority = (max_priority + nominal_priority)/2;
break;
case Thread::THREAD_PRIORITY_NOMINAL:
th_priority = nominal_priority;
break;
case Thread::THREAD_PRIORITY_LOW:
th_priority = (min_priority + nominal_priority)/2;
break;
case Thread::THREAD_PRIORITY_MIN:
th_priority = min_priority;
break;
default:
th_priority = max_priority;
break;
}
status = setpriority(PRIO_PROCESS, thread->getProcessId(),
th_priority);
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
PrintThreadSchedulingInfo(thread);
return status;
};
void ThreadPrivateActions::PushCancelFunction(void (*routine)(void *), void *arg) {
Thread *thread = GetThread(getpid());
if(thread != 0L) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(thread->_prvData);
SprocThreadPrivateData::CancelFuncStruct c;
pd->cancelFuncStack.push(c);
SprocThreadPrivateData::CancelFuncStruct *cft = &(pd->cancelFuncStack.top());
cft->routine = routine;
cft->arg = arg;
}
}
void ThreadPrivateActions::PopCancelFunction() {
Thread *thread = GetThread(getpid());
if(thread != 0L) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(thread->_prvData);
if(!pd->cancelFuncStack.empty())
pd->cancelFuncStack.pop();
}
}
//----------------------------------------------------------------------------
//
// 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();
SprocThreadPrivateData *pd = new SprocThreadPrivateData();
pd->stackSize = 128*1024; // Set a minimum of 128K bytes if possible.
pd->stackSizeLocked = false;
pd->isRunning = false;
pd->isCanceled = false;
pd->idSet = false;
pd->cancelActive = true;
pd->detached = false;
pd->uniqueId = pd->nextId;
pd->nextId++;
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Thread::~Thread()
{
DPRINTF(("(SPROC THREAD) %s:%d, In OpenThreads::Thread destructor\n",
__FILE__, __LINE__));
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *>(_prvData);
if(pd->isRunning)
{
DPRINTF(("(SPROC THREAD) %s:%d, about to kill OpenThreads::Thread\n",
__FILE__, __LINE__));
//-------------------------------------------------------------------
// Kill the process when the thread is destroyed.
//
cancel();
while (pd->isRunning == true) {
::usleep(1);
}
}
DPRINTF(("(SPROC THREAD) %s:%d, Thread destroying private data.\n",
__FILE__, __LINE__));
delete pd;
_prvData = 0;
}
//-----------------------------------------------------------------------------
//
// Description: Initialize Threading
//
// Use: public.
//
void Thread::Init() {
if(s_isInitialized) return;
#ifdef GP_DEBUG
fprintf(stderr, "%s\n", OPENTHREAD_VERSION_STRING);
#endif
s_masterThreadPriority = Thread::THREAD_PRIORITY_MAX;
s_isInitialized = true;
}
//-----------------------------------------------------------------------------
//
// Description: Return a pointer to the currently executing thread
//
// Use: public
//
Thread *Thread::CurrentThread() {
return (*(Thread **)&PRDA->usr_prda);
}
//-----------------------------------------------------------------------------
//
// Description: Get a unique identifier for this thread.
//
// Use: public
//
int Thread::getThreadId() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
return pd->uniqueId;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's process id
//
// Use: public
//
size_t Thread::getProcessId() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
if(pd->idSet == false) return getpid();
return (size_t)(pd->pid);
}
//-----------------------------------------------------------------------------
//
// Description: Determine if the thread is running
//
// Use: public
//
bool Thread::isRunning() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
return pd->isRunning;
}
//-----------------------------------------------------------------------------
//
// Description: Start the thread.
//
// Use: public
//
int Thread::start() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->threadStartedBlock.reset();
int pid = sproc(ThreadPrivateActions::StartThread,
PR_SALL,
static_cast<void *>(this));
// PR_SADDR | PR_SDIR | PR_SUMASK | PR_SULIMIT | PR_SID,
if(pid < 0) {
perror("sproc encountered an error");
return -1;
}
//-----------------------------------------------------------------
// Make the thread runnable anywhere.
//
sysmp(MP_RUNANYWHERE_PID, pid);
pd->pid = pid;
pd->idSet = true;
// 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() {
int status = 0;
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->detached=true;
sigset(SIGCLD, sproc_dead_child_sig_handler);
return status;
}
//-----------------------------------------------------------------------------
//
// Description: Join the thread.
//
// Use: public
//
int Thread::join() {
int status;
return waitpid((pid_t)getProcessId(), &status, 0);
//return status;
}
//-----------------------------------------------------------------------------
//
// Description: test the cancel state of the thread.
//
// Use: public
//
int Thread::testCancel() {
if(getpid() != getProcessId()) return -1;
ThreadPrivateActions::ThreadCancelTest();
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Cancel the thread.
//
// Use: public
//
int Thread::cancel() {
int status = 0;
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
if(pd->cancelActive) {
status = kill((pid_t)getProcessId(), SIGINT);
};
return status;
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->cancelActive = false;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel immediately
//
// Use: public
//
int Thread::setCancelModeAsynchronous() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->cancelActive = true;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel at the next convienent point.
//
// Use: public
//
int Thread::setCancelModeDeferred() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->cancelActive = true;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's schedule priority (if able)
//
// Use: public
//
int Thread::setSchedulePriority(ThreadPriority priority) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
pd->threadPriority = priority;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's schedule priority (if able)
//
// Use: public
//
int Thread::getSchedulePriority() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
return pd->threadPriority;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::setSchedulePolicy(ThreadPolicy policy) {
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::getSchedulePolicy() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
return pd->threadPolicy;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's desired stack size
//
// Use: public
//
int Thread::setStackSize(size_t stackSize) {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
if(pd->stackSizeLocked == true) return 13; // EACESS
pd->stackSize = stackSize;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's stack size.
//
// Use: public
//
size_t Thread::getStackSize() {
SprocThreadPrivateData *pd =
static_cast<SprocThreadPrivateData *> (_prvData);
return pd->stackSize;
}
//-----------------------------------------------------------------------------
//
// Description: Print the thread's scheduling information to stdout.
//
// Use: public
//
void Thread::printSchedulingInfo() {
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
}
//-----------------------------------------------------------------------------
//
// Description: Yield the processor
//
// Use: protected
//
int Thread::YieldCurrentThread() {
return sched_yield();
}
//-----------------------------------------------------------------------------
// Description: sleep
//
// Use: public
//
int Thread::microSleep(unsigned int microsec)
{
return ::usleep(microsec);
}
static void sproc_dead_child_sig_handler(int sigid) {
#ifdef DEBUG
int pid, status;
pid = wait(&status);
DPRINTF(("(SPROC THREAD) Dead Child Handler Caught Signal, Reaped %d\n",
pid));
#endif
sigset(SIGCLD, sproc_dead_child_sig_handler);
}
int Thread::setProcessorAffinity( unsigned int cpunum )
{
return -1;
}
//-----------------------------------------------------------------------------
//
// Description: Get the number of processors
//
int OpenThreads::GetNumberOfProcessors()
{
return 1;
}
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
{
if (cpunum<0) return -1;
Thread::Init();
Thread* thread = Thread::CurrentThread();
if (thread)
{
return thread->setProcessorAffinity(cpunum);
}
else
{
// non op right now, needs implementation.
return -1;
}
}

View File

@ -0,0 +1,71 @@
/* -*-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.
*/
//
// SprocThreadPrivateActions.c++ - Thread private actions for sprocs
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <OpenThreads/Thread>
#include <list>
#ifndef SPROC_THREAD_PRIVATE_ACTIONS
#define SPROC_THREAD_PRIVATE_ACTIONS
namespace OpenThreads {
class ThreadPrivateActions {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can issue the methods.
//
friend class Thread;
public:
static void ThreadCancelTest();
static void PushCancelFunction(void (*routine)(void *), void *arg);
static void PopCancelFunction();
private:
static bool *GetDeathFlag(Thread *thread);
static Thread *GetThread(pid_t thread_id);
static void ThreadCancelHandler(int sigid);
//-------------------------------------------------------------------------
// standard start routine.
//
static void StartThread(void *data);
static void AddThread(Thread *thread);
static void RemoveThread(Thread *thread);
static void PrintThreadSchedulingInfo(Thread *thread);
static int SetThreadSchedulingParams(Thread *thread);
private:
static std::list<Thread *> s_threadList;
};
}
#endif // !SPROC_THREAD_PRIVATE_ACTIONS

View File

@ -0,0 +1,84 @@
/* -*-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.
*/
//
//
// SprocThreadPrivateData.h - private data for sproc thread
// ~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef _SPROCTHREADPRIVATEDATA_H_
#define _SPROCTHREADPRIVATEDATA_H_
#include <sys/types.h>
#include <ulocks.h>
#include <stack>
#include <OpenThreads/Thread>
#include <OpenThreads/Block>
#include "SprocThreadPrivateActions.h"
namespace OpenThreads {
class SprocThreadPrivateData {
friend class Thread;
friend class ThreadPrivateActions;
private:
struct CancelFuncStruct {
void (*routine)(void *);
void *arg;
};
SprocThreadPrivateData() {};
virtual ~SprocThreadPrivateData() {};
volatile unsigned int stackSize;
volatile bool stackSizeLocked;
volatile bool isRunning;
Block threadStartedBlock;
volatile bool isCanceled;
volatile bool idSet;
volatile bool cancelActive;
volatile bool detached;
volatile bool dieFlag;
volatile Thread::ThreadPriority threadPriority;
volatile Thread::ThreadPolicy threadPolicy;
volatile pid_t pid;
volatile int uniqueId;
std::stack<CancelFuncStruct> cancelFuncStack;
static int nextId;
};
}
#endif // !_SPROCTHREADPRIVATEDATA_H_

View File

@ -0,0 +1,52 @@
# This file should only be included when WIN32
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)
ADD_LIBRARY(${LIB_NAME}
${OPENTHREADS_USER_DEFINED_DYNAMIC_OR_STATIC}
${LIB_PUBLIC_HEADERS}
HandleHolder.h
Win32BarrierPrivateData.h
WIN32Condition.cpp
Win32Condition.h
Win32ConditionPrivateData.h
Win32Mutex.cpp
Win32MutexPrivateData.h
Win32Thread.cpp
Win32ThreadBarrier.cpp
Win32ThreadPrivateData.h
../common/Version.cpp
)
IF(OPENTHREADS_SONAMES)
SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${OPENTHREADS_VERSION} SOVERSION ${OPENTHREADS_SOVERSION})
ENDIF(OPENTHREADS_SONAMES)
# 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(MSVC AND OSG_MSVC_VERSIONED_DLL)
INSTALL(
TARGETS OpenThreads
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
INSTALL(
FILES ${OpenThreads_PUBLIC_HEADERS}
DESTINATION include/OpenThreads
)
#commented out# INCLUDE(ModuleInstall OPTIONAL)

View File

@ -0,0 +1,38 @@
TOPDIR = ../.
include $(TOPDIR)/Make/makedefs
CXXFILES = \
WIN32Condition.cpp \
Win32Mutex.cpp \
Win32Thread.cpp \
Win32ThreadBarrier.cpp \
$(NULL)
INC += -I$(TOPDIR)/include -I.
ifeq ($(OS),Linux)
DEF += -fPIC -DLinux -DGL_GLEXT_PROTOTYPES
LIBS += -lpthread
endif
ifeq ($(OS),SunOS)
LIBS += -lpthread -lposix4
endif
ifeq ($(OS),IRIX)
LIBS += -lpthread
endif
ifeq ($(OS),Darwin)
LIBS += -lpthread
endif
ifeq ($(OS),MINGW)
LIBS +=
DEF += -DOPENTHREADS_EXPORTS
endif
TARGET_BASENAME = OpenThreads
LIB = $(LIB_PREFIX)$(TARGET_BASENAME)
include $(TOPDIR)/Make/makerules

View File

@ -0,0 +1,89 @@
/* -*-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.
*/
//
//
// Win32BarrierPrivateData.h - private data structure for barrier
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _HandleHolder_H_
#define _HandleHolder_H_
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
/************************************************************************/
/* Class that holds HANDLES ensuring proper destruction */
/* It is design decision to make this class noncopyable. */
/* It makes design much cleaner. If one wants to copy handle than one */
/* can do hv.set(DuplicateHandle(....)) */
/************************************************************************/
namespace OpenThreads {
class HandleHolder{
private:
HANDLE _handle;
inline void close(){
if( _handle != INVALID_HANDLE_VALUE) CloseHandle(_handle);
_handle = INVALID_HANDLE_VALUE;
};
// copy constructor - disallow
HandleHolder(const HandleHolder& rhs);
// assignment operator - disallow
HandleHolder& operator=(const HandleHolder& rhs );
public:
// constructor
HandleHolder()
:_handle(INVALID_HANDLE_VALUE)
{};
// constructor from HANDLE
explicit HandleHolder(HANDLE h)
:_handle(h)
{};
// destructor - CloseHandle()
~HandleHolder()
{
close();
};
// accessor
const HANDLE& get() const {
return _handle;
}
// mutator
void set (HANDLE h) {
if( _handle != INVALID_HANDLE_VALUE ) close();
_handle = h;
}
operator bool (){
return _handle != INVALID_HANDLE_VALUE && _handle != NULL;
};
};
} // namespace
#endif

View File

@ -0,0 +1,18 @@
# Makefile - OpenThreads.dsw
.PHONY: all
all: \
OpenThreads
.PHONY: OpenThreads
OpenThreads:
$(MAKE) -f OpenThreads.mak
.PHONY: clean
clean:
$(MAKE) -f OpenThreads.mak clean
.PHONY: depends
depends:
$(MAKE) -f OpenThreads.mak depends

View File

@ -0,0 +1,231 @@
# Microsoft Developer Studio Project File - Name="OpenThreads" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=OpenThreads - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "OpenThreads.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "OpenThreads.mak" CFG="OpenThreads - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "OpenThreads - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "OpenThreads - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "OpenThreads - Win32 Release Static" (based on "Win32 (x86) Static Library")
!MESSAGE "OpenThreads - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
!IF "$(CFG)" == "OpenThreads - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../bin/$(PlatformName)"
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
CPP=cl.exe
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /opt:ref /opt:icf /out:"$(OutDir)/OpenThreadsWin32.dll" /implib:"../lib/$(PlatformName)/OpenThreadsWin32.lib"
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../bin/$(PlatformName)"
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /out:"$(OutDir)/OpenThreadsWin32d.dll" /implib:"../lib/$(PlatformName)/OpenThreadsWin32d.lib"
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_Static"
# PROP BASE Intermediate_Dir "Release_Static"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../lib/$(PlatformName)"
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
CPP=cl.exe
# ADD BASE CPP /nologo /MT /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /D "OPENTHREADS_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /YX /FD /c
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"../lib/$(PlatformName)/OpenThreadsWin32_s.lib"
!ELSEIF "$(CFG)" == "OpenThreads - Win32 Debug Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_Static"
# PROP BASE Intermediate_Dir "Debug_Static"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../lib/$(PlatformName)"
# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /W3 /Gm /GR /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /D "OPENTHREADS_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "OT_LIBRARY_STATIC" /YX /FD /GZ /c
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"../lib/$(PlatformName)/OpenThreadsWin32d_s.lib"
!ENDIF
# Begin Target
# Name "OpenThreads - Win32 Release"
# Name "OpenThreads - Win32 Debug"
# Name "OpenThreads - Win32 Release Static"
# Name "OpenThreads - Win32 Debug Static"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\WIN32Condition.cpp
# End Source File
# Begin Source File
SOURCE=.\Win32Mutex.cpp
# End Source File
# Begin Source File
SOURCE=.\Win32Thread.cpp
# End Source File
# Begin Source File
SOURCE=.\Win32ThreadBarrier.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\include\OpenThreads\Barrier
# End Source File
# Begin Source File
SOURCE=..\include\OpenThreads\Condition
# End Source File
# Begin Source File
SOURCE=..\include\OpenThreads\Exports
# End Source File
# Begin Source File
SOURCE=.\HandleHolder.h
# End Source File
# Begin Source File
SOURCE=..\include\OpenThreads\Mutex
# End Source File
# Begin Source File
SOURCE=..\include\OpenThreads\ScopedLock
# End Source File
# Begin Source File
SOURCE=..\include\OpenThreads\Thread
# End Source File
# Begin Source File
SOURCE=.\Win32BarrierPrivateData.h
# End Source File
# Begin Source File
SOURCE=.\Win32ConditionPrivateData.h
# End Source File
# Begin Source File
SOURCE=.\Win32MutexPrivateData.h
# End Source File
# Begin Source File
SOURCE=.\Win32ThreadPrivateData.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "OpenThreads"=.\OpenThreads.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -0,0 +1,89 @@
# Makefile - OpenThreads.dsp
ifndef CFG
CFG=OpenThreads - Win32 Release
endif
CC=gcc
CFLAGS=
CXX=g++
CXXFLAGS=$(CFLAGS)
RC=windres -O COFF
ifeq "$(CFG)" "OpenThreads - Win32 Release"
CFLAGS+=-W -fexceptions -O2 -I../include -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DOPENTHREADS_EXPORTS
LD=g++
LDFLAGS=-shared -Wl,--out-implib,../bin/Win32/OpenThreadsWin32.dll.a -Wl,--export-all-symbols
TARGET=../bin/Win32/OpenThreadsWin32.dll
LDFLAGS+=
LIBS+=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
else
ifeq "$(CFG)" "OpenThreads - Win32 Debug"
CFLAGS+=-W -fexceptions -g -O0 -I../include -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DOPENTHREADS_EXPORTS
LD=g++
LDFLAGS=-shared -Wl,--out-implib,../bin/Win32/OpenThreadsWin32d.dll.a -Wl,--export-all-symbols
TARGET=../bin/Win32/OpenThreadsWin32d.dll
LDFLAGS+=
LIBS+=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
endif
endif
ifndef TARGET
TARGET=OpenThreads.dll
endif
.PHONY: all
all: $(TARGET)
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
%.o: %.cc
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
%.o: %.cxx
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
%.res: %.rc
$(RC) $(CPPFLAGS) -o $@ -i $<
SOURCE_FILES= \
WIN32Condition.cpp \
Win32Mutex.cpp \
Win32Thread.cpp \
Win32ThreadBarrier.cpp
HEADER_FILES= \
../include/OpenThreads/Barrier \
../include/OpenThreads/Condition \
../include/OpenThreads/Exports \
../include/OpenThreads/Mutex \
../include/OpenThreads/ScopedLock \
../include/OpenThreads/Thread \
Win32BarrierPrivateData.h \
Win32Condition.h \
Win32ConditionPrivateData.h \
Win32MutexPrivateData.h \
Win32ThreadPrivateData.h \
HandleHolder.h
RESOURCE_FILES=
SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES)
OBJS=$(patsubst %.rc,%.res,$(patsubst %.cxx,%.o,$(patsubst %.cpp,%.o,$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(filter %.c %.cc %.cpp %.cxx %.rc,$(SRCS)))))))
$(TARGET): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
.PHONY: clean
clean:
-rm -f $(OBJS) $(TARGET) OpenThreads.dep
.PHONY: depends
depends:
-$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cc %.cpp %.cxx,$(SRCS)) > OpenThreads.dep
-include OpenThreads.dep

View File

@ -0,0 +1,100 @@
/* -*-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.
*/
//
// Win32Condition.c++ - C++ Condition class built on top of posix threads.
// ~~~~~~~~~~~~~~~~~~~~
//
#include <OpenThreads/Condition>
#include <OpenThreads/Thread>
#include "Win32ConditionPrivateData.h"
using namespace OpenThreads;
Win32ConditionPrivateData::~Win32ConditionPrivateData()
{
}
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Condition::Condition() {
Win32ConditionPrivateData *pd =
new Win32ConditionPrivateData();
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Condition::~Condition() {
Win32ConditionPrivateData *pd =
static_cast<Win32ConditionPrivateData *>(_prvData);
delete pd;
}
//----------------------------------------------------------------------------
//
// Description: wait on a condition
//
// Use: public.
//
int Condition::wait(Mutex *mutex) {
Win32ConditionPrivateData *pd =
static_cast<Win32ConditionPrivateData *>(_prvData);
return pd->wait(*mutex, INFINITE);
}
//----------------------------------------------------------------------------
//
// Description: wait on a condition, for a specified period of time
//
// Use: public.
//
int Condition::wait(Mutex *mutex, unsigned long ms) {
Win32ConditionPrivateData *pd =
static_cast<Win32ConditionPrivateData *>(_prvData);
return pd->wait(*mutex, ms);
}
//----------------------------------------------------------------------------
//
// Description: signal a thread to wake up.
//
// Use: public.
//
int Condition::signal() {
Win32ConditionPrivateData *pd =
static_cast<Win32ConditionPrivateData *>(_prvData);
return pd->signal();
}
//----------------------------------------------------------------------------
//
// Description: signal many threads to wake up.
//
// Use: public.
//
int Condition::broadcast() {
Win32ConditionPrivateData *pd =
static_cast<Win32ConditionPrivateData *>(_prvData);
return pd->broadcast();
}

View File

@ -0,0 +1,69 @@
/* -*-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.
*/
//
// Win32BarrierPrivateData.h - private data structure for barrier
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _Win32BARRIERPRIVATEDATA_H_
#define _Win32BARRIERPRIVATEDATA_H_
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <OpenThreads/Mutex>
#include <OpenThreads/Condition>
namespace OpenThreads {
class Barrier;
class Win32BarrierPrivateData {
friend class Barrier;
private:
Win32BarrierPrivateData() {};
~Win32BarrierPrivateData();
Condition cond; // cv for waiters at barrier
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 //_Win32BARRIERPRIVATEDATA_H_

View File

@ -0,0 +1,159 @@
/* -*-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.
*/
#ifndef _WIN32VODITIONPRODUCER_CONDITION
#define PRODUCER_CONDITION
#ifdef WIN32
#include "Mutex.h"
namespace OpenThreads {
class Win32ConditionImpl
{
public:
/// number of waiters.
long waiters_;
Condition(long max = 0L)
{
waiters_ = 0;
sema_ = CreateSemaphore(NULL,0,0x7fffffff,NULL);
waiters_done_ = CreateEvent(NULL,FALSE,FALSE,NULL);
}
~Condition()
{
// CloseHandle(sema_);
// CloseHandle(waiters_done_);
}
inline int broadcast ()
{
waiters_lock_.lock();
int have_waiters = 0;
if (waiters_ > 0)
{
// We are broadcasting, even if there is just one waiter...
// Record the fact that we are broadcasting. This helps the
// wait() method know how to optimize itself. Be sure to
// set this with the <waiters_lock_> held.
was_broadcast_ = 1;
have_waiters = 1;
}
waiters_lock_.unlock();
int result = 0;
if (have_waiters)
{
// Wake up all the waiters.
ReleaseSemaphore(sema_,waiters_,NULL);
WaitForSingleObject(waiters_done_,INFINITE) ;
// This is okay, even without the <waiters_lock_> held because
// no other waiter threads can wake up to access it.
was_broadcast_ = 0;
}
return result;
}
inline int wait (Mutex& external_mutex)
{
// Prevent race conditions on the <waiters_> count.
waiters_lock_.lock();
waiters_++;
waiters_lock_.unlock();
int result = 0;
external_mutex.unlock();
DWORD dwResult = WaitForSingleObject(sema_,INFINITE);
if(dwResult != WAIT_OBJECT_0)
result = (int)dwResult;
// Reacquire lock to avoid race conditions on the <waiters_> count.
waiters_lock_.lock();
// We're ready to return, so there's one less waiter.
waiters_--;
int last_waiter = was_broadcast_ && waiters_ == 0;
// Release the lock so that other collaborating threads can make
// progress.
waiters_lock_.unlock();
if (result != -1 && last_waiter)
SetEvent(waiters_done_);
external_mutex.lock();
return result;
}
protected:
/// Serialize access to the waiters count.
Mutex waiters_lock_;
/// Queue up threads waiting for the condition to become signaled.
HANDLE sema_;
/**
* An auto reset event used by the broadcast/signal thread to wait
* for the waiting thread(s) to wake up and get a chance at the
* semaphore.
*/
HANDLE waiters_done_;
/// Keeps track of whether we were broadcasting or just signaling.
size_t was_broadcast_;
};
#else
#include <pthread.h>
namespace Producer {
class PR_EXPORT Condition
{
public:
/// number of waiters.
Condition(long max)
{
pthread_cond_init( &_cond, 0L );
}
~Condition()
{
}
inline int broadcast ()
{
return pthread_cond_broadcast(&_cond);
}
inline int wait (Mutex& external_mutex)
{
return pthread_cond_wait(&_cond);
}
protected:
pthread_cond_t _cond;
};
#endif
}
#endif

View File

@ -0,0 +1,163 @@
/* -*-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.
*/
//
//
// WIN32ConditionPrivateData.h - Private data structure for Condition
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _WIN32CONDITIONPRIVATEDATA_H_
#define _WIN32CONDITIONPRIVATEDATA_H_
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <OpenThreads/ScopedLock>
#include "Win32ThreadPrivateData.h"
#include "HandleHolder.h"
#define InterlockedGet(x) InterlockedExchangeAdd(x,0)
namespace OpenThreads {
class Condition;
class Win32ConditionPrivateData {
public:
friend class Condition;
/// number of waiters.
long waiters_;
Win32ConditionPrivateData ()
:waiters_(0),
sema_(CreateSemaphore(NULL,0,0x7fffffff,NULL)),
waiters_done_(CreateEvent(NULL,FALSE,FALSE,NULL))
{
}
~Win32ConditionPrivateData ();
inline int broadcast ()
{
int have_waiters = 0;
long w = InterlockedGet(&waiters_);
if (w > 0)
{
// we are broadcasting.
was_broadcast_ = 1;
have_waiters = 1;
}
int result = 0;
if (have_waiters)
{
// Wake up all the waiters.
ReleaseSemaphore(sema_.get(),waiters_,NULL);
cooperativeWait(waiters_done_.get(), INFINITE);
//end of broadcasting
was_broadcast_ = 0;
}
return result;
}
inline int signal()
{
long w = InterlockedGet(&waiters_);
int have_waiters = w > 0;
int result = 0;
if (have_waiters)
{
if( !ReleaseSemaphore(sema_.get(),1,NULL) )
result = -1;
}
return result;
}
inline int wait (Mutex& external_mutex, long timeout_ms)
{
// Prevent race conditions on the <waiters_> count.
InterlockedIncrement(&waiters_);
int result = 0;
ReverseScopedLock<Mutex> lock(external_mutex);
// wait in timeslices, giving testCancel() a change to
// exit the thread if requested.
try {
DWORD dwResult = cooperativeWait(sema_.get(), timeout_ms);
if(dwResult != WAIT_OBJECT_0)
result = (int)dwResult;
}
catch(...){
// thread is canceled in cooperative wait , do cleanup
InterlockedDecrement(&waiters_);
long w = InterlockedGet(&waiters_);
int last_waiter = was_broadcast_ && w == 0;
if (last_waiter) SetEvent(waiters_done_.get());
// rethrow
throw;
}
// We're ready to return, so there's one less waiter.
InterlockedDecrement(&waiters_);
long w = InterlockedGet(&waiters_);
int last_waiter = was_broadcast_ && w == 0;
if (result != -1 && last_waiter)
SetEvent(waiters_done_.get());
return result;
}
protected:
/// Serialize access to the waiters count.
/// Mutex waiters_lock_;
/// Queue up threads waiting for the condition to become signaled.
HandleHolder sema_;
/**
* An auto reset event used by the broadcast/signal thread to wait
* for the waiting thread(s) to wake up and get a chance at the
* semaphore.
*/
HandleHolder waiters_done_;
/// Keeps track of whether we were broadcasting or just signaling.
size_t was_broadcast_;
};
#undef InterlockedGet
}
#endif // !_WIN32CONDITIONPRIVATEDATA_H_

View File

@ -0,0 +1,222 @@
/* -*-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.
*/
//
//
// Win32Mutex.c++ - C++ Mutex class .
// The idea for it is borrowed from SGI STL
// It looks like it's hard to use win32 CRITICALL_SECTIONS withour introducing race
// conditions on InitializeCriticalSection() . So we use spin mutex here.
// ~~~~~~~~~~~~~~~~
//
#include <OpenThreads/Mutex>
#include "Win32MutexPrivateData.h"
using namespace OpenThreads;
Win32MutexPrivateData::Win32MutexPrivateData()
{
#ifdef USE_CRITICAL_SECTION
InitializeCriticalSection( &_cs );
#else
mutex = 0;
#endif
}
Win32MutexPrivateData::~Win32MutexPrivateData()
{
#ifdef USE_CRITICAL_SECTION
DeleteCriticalSection( &_cs );
#endif
}
#ifndef USE_CRITICAL_SECTION
template <int instance>
struct WIN32MutexSpin {
enum { __low_max = 30, __high_max = 1000 };
// Low if we suspect uniprocessor, high for multiprocessor.
static unsigned __max;
static unsigned __last;
};
template <int instance>
unsigned WIN32MutexSpin <instance>::__max = WIN32MutexSpin <instance>::__low_max;
template <int instance>
unsigned WIN32MutexSpin <instance>::__last = 0;
static void _S_nsec_sleep(int __log_nsec) {
if (__log_nsec <= 20) {
SwitchToThread(); //Sleep(0); // adegli replaced it Sleep by SwitchToThread
} else {
Sleep(1 << (__log_nsec - 20));
}
}
#if defined(_MSC_VER) && _MSC_VER <= 1300
template WIN32MutexSpin <0>;
#endif
#endif // USE_CRITICAL_SECTION
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Mutex::Mutex() {
Win32MutexPrivateData *pd = new Win32MutexPrivateData();
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Mutex::~Mutex() {
unlock();
delete static_cast<Win32MutexPrivateData*>(_prvData);
}
//----------------------------------------------------------------------------
//
// Description: lock the mutex
//
// Use: public.
//
int Mutex::lock() {
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
#ifdef USE_CRITICAL_SECTION
// Block until we can take this lock.
EnterCriticalSection( &(pd->_cs) );
return 0;
#else
volatile unsigned long* lock = &pd->mutex;
// InterlockedExchange returns old value
// if old_value == 0 mutex wasn't locked , now it is
if( !InterlockedExchange((long*)lock, 1L)) {
return 0;
}
unsigned my_spin_max = WIN32MutexSpin<0>::__max;
unsigned my_last_spins = WIN32MutexSpin<0>::__last;
volatile unsigned junk = 17;
unsigned i;
for (i = 0; i < my_spin_max; i++) {
if (i < my_last_spins/2 || *lock) {
junk *= junk; junk *= junk;
junk *= junk; junk *= junk;
continue;
}
if (!InterlockedExchange((long*)lock, 1L)) {
// got it!
// Spinning worked. Thus we're probably not being scheduled
// against the other process with which we were contending.
// Thus it makes sense to spin longer the next time.
WIN32MutexSpin<0>::__last = i;
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__high_max;
return 0;
}
}
// We are probably being scheduled against the other process. Sleep.
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__low_max;
for (i = 0 ;; ++i) {
int __log_nsec = i + 6;
if (__log_nsec > 27) __log_nsec = 27;
if (!InterlockedExchange((long*)lock, 1L)) {
return 0;
}
_S_nsec_sleep(__log_nsec);
}
return -1;
#endif // USE_CRITICAL_SECTION
}
//----------------------------------------------------------------------------
//
// Description: unlock the mutex
//
// Use: public.
//
int Mutex::unlock() {
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
#ifdef USE_CRITICAL_SECTION
// Release this lock. CRITICAL_SECTION is nested, thus
// unlock() calls must be paired with lock() calls.
LeaveCriticalSection( &(pd->_cs) );
return 0;
#else
volatile unsigned long* lock = &pd->mutex;
*lock = 0;
// This is not sufficient on many multiprocessors, since
// writes to protected variables and the lock may be reordered.
return 0;
#endif // USE_CRITICAL_SECTION
}
//----------------------------------------------------------------------------
//
// Description: test if the mutex may be locked
//
// Use: public.
//
int Mutex::trylock() {
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
#ifdef USE_CRITICAL_SECTION
// Take the lock if we can; regardless don't block.
// 'result' is FALSE if we took the lock or already held
// it amd TRUE if another thread already owns the lock.
BOOL result = TryEnterCriticalSection( &(pd->_cs) );
return( (result==TRUE) ? 0 : 1 );
#else
volatile unsigned long* lock = &pd->mutex;
if( !InterlockedExchange((long*)lock, 1L)) {
return 1; // TRUE
}
return 0; // FALSE
#endif // USE_CRITICAL_SECTION
}

View File

@ -0,0 +1,55 @@
/* -*-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.
*/
//
// Win32MutexPrivateData.h - Private data structure for Mutex
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
#ifndef _Win32MUTEXPRIVATEDATA_H_
#define _Win32MUTEXPRIVATEDATA_H_
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0400 // was missing : adegli
#include <windows.h>
#endif
namespace OpenThreads {
class Win32MutexPrivateData {
friend class Mutex;
friend class Condition;
private:
Win32MutexPrivateData();
~Win32MutexPrivateData();
#define USE_CRITICAL_SECTION
#ifdef USE_CRITICAL_SECTION
CRITICAL_SECTION _cs;
#else
volatile unsigned long mutex;
#endif
};
}
#endif // !_Win32MUTEXPRIVATEDATA_H_

View File

@ -0,0 +1,682 @@
/* -*-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.
*/
//
// Win32Thread.c++
// ~~~~~~~~~~~
#include <memory>
#include <string>
#include <iostream>
#include <process.h>
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#ifdef __SGI_STL
using std::size_t;
#endif
#else
using std::size_t;
#endif
#if defined(_MSC_VER)
#pragma warning( disable : 4996 )
#endif
#include "Win32ThreadPrivateData.h"
struct Win32ThreadCanceled{};
using namespace OpenThreads;
DWORD OpenThreads::cooperativeWait(HANDLE waitHandle, unsigned long timeout){
Thread* current = Thread::CurrentThread();
DWORD dwResult ;
if(current)
{
HANDLE cancelHandle = static_cast<Win32ThreadPrivateData*>(current->getImplementation())->cancelEvent.get();
HANDLE handleSet[2] = {waitHandle, cancelHandle};
dwResult = WaitForMultipleObjects(2,handleSet,FALSE,timeout);
if(dwResult == WAIT_OBJECT_0 + 1 ) throw Win32ThreadCanceled();
}
else
{
dwResult = WaitForSingleObject(waitHandle,timeout);
}
return dwResult;
}
Win32ThreadPrivateData::TlsHolder Win32ThreadPrivateData::TLS;
Win32ThreadPrivateData::~Win32ThreadPrivateData()
{
}
const std::string OPENTHREAD_VERSION_STRING = "OpenThread v1.2preAlpha, WindowThreads (Public Implementation)";
//-----------------------------------------------------------------------------
// Initialize thread master priority level
//
Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
bool Thread::s_isInitialized = false;
//-----------------------------------------------------------------------------
// Class to support some static methods necessary for pthread's to work
// correctly.
//
namespace OpenThreads {
class ThreadPrivateActions {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can issue the methods.
//
friend class Thread;
private:
//-------------------------------------------------------------------------
// Win32Threads standard start routine.
//
static unsigned int __stdcall StartThread(void *data) {
Thread *thread = static_cast<Thread *>(data);
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
if (thread->_prvData==0) return 0;
TlsSetValue(Win32ThreadPrivateData::TLS.ID ,data);
//---------------------------------------------------------------------
// Set the proper scheduling priorities
//
SetThreadSchedulingParams(thread);
pd->isRunning = true;
// release the thread that created this thread.
pd->threadStartedBlock.release();
try{
thread->run();
}
catch(Win32ThreadCanceled&)
{
// thread is canceled do cleanup
try {
thread->cancelCleanup();
} catch(...) { }
}
catch(...)
{
// abnormal termination but must be caught in win32 anyway
}
pd->isRunning = false;
return 0;
};
//-------------------------------------------------------------------------
// Print information related to thread schduling parameters.
//
static void PrintThreadSchedulingInfo(Thread *thread) {
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
std::cout<<"Thread "<< thread <<" priority : ";
switch(thread->getSchedulePriority()) {
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;
}
}
//--------------------------------------------------------------------------
// Set thread scheduling parameters.
// Note that time-critical priority is ommited :
// 1) It's not sensible thing to do
// 2) there's no enum for that in Thread interface
// Also, on Windows, effective thread priority is :
// process priority (manipulated with Get/SetProrityClass) + thread priority (here).
//
//
static int SetThreadSchedulingParams(Thread *thread) {
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
int prio = THREAD_PRIORITY_NORMAL;
switch(thread->getSchedulePriority()) {
case Thread::THREAD_PRIORITY_MAX:
prio = THREAD_PRIORITY_HIGHEST;
break;
case Thread::THREAD_PRIORITY_HIGH:
prio = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case Thread::THREAD_PRIORITY_NOMINAL:
prio = THREAD_PRIORITY_NORMAL;
break;
case Thread::THREAD_PRIORITY_LOW:
prio = THREAD_PRIORITY_BELOW_NORMAL;
break;
case Thread::THREAD_PRIORITY_MIN:
prio = THREAD_PRIORITY_IDLE;
break;
}
int status = SetThreadPriority( pd->tid.get(), prio);
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
PrintThreadSchedulingInfo(thread);
return status!=0;
};
};
};
Thread* Thread::CurrentThread()
{
return (Thread* )TlsGetValue(Win32ThreadPrivateData::TLS.ID);
};
//----------------------------------------------------------------------------
//
// Description: Set the concurrency level (no-op)
//
// Use static public
//
int Thread::SetConcurrency(int) {
return -1;
};
//----------------------------------------------------------------------------
//
// Description: Get the concurrency level
//
// Use static public
//
int Thread::GetConcurrency() {
return -1;
};
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Thread::Thread() {
// there's no need for this
// if(!s_isInitialized) Init();
Win32ThreadPrivateData *pd = new Win32ThreadPrivateData();
pd->stackSize = 0;
pd->isRunning = false;
pd->cancelMode = 0;
pd->uniqueId = 0;
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
pd->detached = false;
pd->cancelEvent.set(CreateEvent(NULL,TRUE,FALSE,NULL));
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Thread::~Thread()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(_prvData);
if(pd->isRunning)
{
std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
pd->cancelMode = 0;
cancel();
}
delete pd;
_prvData = 0;
}
//-----------------------------------------------------------------------------
//
// Description: Initialize Threading
//
// Use: public.
//
void Thread::Init() {
// if(s_isInitialized) return;
// s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
s_isInitialized = true;
}
//-----------------------------------------------------------------------------
//
// Description: Get a unique identifier for this thread.
//
// Use: public
//
int Thread::getThreadId() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->uniqueId;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's process id
//
// Use: public
//
size_t Thread::getProcessId() {
return (size_t) GetCurrentProcessId();
}
//-----------------------------------------------------------------------------
//
// Description: Determine if the thread is running
//
// Use: public
//
bool Thread::isRunning() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->isRunning;
}
//-----------------------------------------------------------------------------
//
// Description: Start the thread.
//
// Use: public
//
int Thread::start() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
//-------------------------------------------------------------------------
// Prohibit the stack size from being changed.
// (bb 5/13/2005) it actually doesn't matter.
// 1) usually setStackSize()/start() sequence is serialized.
// 2) if not than we're in trouble anyway - nothing is protected
// pd->stackSizeLocked = true;
unsigned int ID;
pd->threadStartedBlock.reset();
pd->tid.set( (void*)_beginthreadex(NULL,pd->stackSize,ThreadPrivateActions::StartThread,static_cast<void *>(this),0,&ID));
pd->uniqueId = (int)ID;
// wait till the thread has actually started.
pd->threadStartedBlock.block();
if(!pd->tid) {
return -1;
}
return 0;
}
int Thread::startThread()
{
if (_prvData) return start();
else return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Join the thread.
//
// Use: public
//
int Thread::join() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if( pd->detached )
return -1; // cannot wait for detached ;
if( WaitForSingleObject(pd->tid.get(),INFINITE) != WAIT_OBJECT_0)
return -1 ;
return 0;
}
int Thread::detach()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->detached = true;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Cancel the thread.
//
// Use: public
//
int Thread::cancel()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if (pd->isRunning)
{
if( pd->cancelMode == 2 )
return -1;
// signal all interested parties that we are going to exit
SetEvent(pd->cancelEvent.get());
// cancelMode == 1 (asynch)-> kill em
// cancelMode == 0 (deffered) -> wait a little then kill em
// if( (pd->cancelMode == 1) || (WaitForSingleObject(pd->tid,INFINITE)!=WAIT_OBJECT_0) )
if( pd->cancelMode == 1 )
{
// did not terminate cleanly force termination
pd->isRunning = false;
return TerminateThread(pd->tid.get(),(DWORD)-1);
}
}
return 0;
}
int Thread::testCancel()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if(WaitForSingleObject(pd->cancelEvent.get(),0) != WAIT_OBJECT_0) return 0;
if(pd->cancelMode == 2)
return 0;
DWORD curr = GetCurrentThreadId();
if( pd->uniqueId != (int)curr )
return -1;
// pd->isRunning = false;
// ExitThread(0);
throw Win32ThreadCanceled();
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 2;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel immediately
//
// Use: public
//
int Thread::setCancelModeAsynchronous() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 1;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel at the next convenient point.
//
// Use: public
//
int Thread::setCancelModeDeferred() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 0;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's schedule priority (if able)
//
// Use: public
//
int Thread::setSchedulePriority(ThreadPriority priority) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->threadPriority = priority;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's schedule priority (if able)
//
// Use: public
//
int Thread::getSchedulePriority() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->threadPriority;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::setSchedulePolicy(ThreadPolicy policy) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->threadPolicy = policy;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::getSchedulePolicy() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->threadPolicy;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's desired stack size
//
// Use: public
//
int Thread::setStackSize(size_t stackSize) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if(pd->isRunning) return 13; // cannot set stack size of running thread return EACESS
pd->stackSize = stackSize;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's stack size.
//
// Use: public
//
size_t Thread::getStackSize() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->stackSize;
}
//-----------------------------------------------------------------------------
//
// Description: set processor affinity for the thread
//
// Use: public
//
int Thread::setProcessorAffinity( unsigned int cpunum )
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
DWORD affinityMask = 0x1 << cpunum ; // thread affinity mask
DWORD_PTR res =
SetThreadAffinityMask
(
pd->tid.get(), // handle to thread
affinityMask // thread affinity mask
);
/*
This one is funny.
This is "non-mandatory" affinity , windows will try to use dwIdealProcessor
whenever possible ( when Bill's account is over 50B, maybe :-) ).
DWORD SetThreadIdealProcessor(
HANDLE hThread, // handle to the thread
DWORD dwIdealProcessor // ideal processor number
);
*/
// return value 1 means call is ignored ( 9x/ME/SE )
if( res == 1 ) return -1;
// return value 0 is failure
return (res == 0) ? GetLastError() : 0 ;
}
//-----------------------------------------------------------------------------
//
// Description: Print the thread's scheduling information to stdout.
//
// Use: public
//
void Thread::printSchedulingInfo() {
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
}
//-----------------------------------------------------------------------------
//
// Description: Yield the processor
//
// Use: protected
//
#if _WIN32_WINNT < 0x0400 // simulate
int SwitchToThread (void)
{
::Sleep(10);
return 0;
};
#endif
int Thread::YieldCurrentThread()
{
return SwitchToThread();
}
int Thread::microSleep(unsigned int microsec)
{
#if _WIN32_WINNT < 0x0400 // simulate
::Sleep(microsec/1000);
return 0;
#else
HandleHolder sleepTimer(CreateWaitableTimer(NULL, TRUE, NULL));
if( !sleepTimer )
return -1;
LARGE_INTEGER t;
t.QuadPart= -(LONGLONG)microsec*10; // in 100ns units
// negative sign means relative,
if (!SetWaitableTimer(sleepTimer.get(), &t, 0, NULL, NULL, 0))
{
return -1;
}
// Wait for the timer.
if (WaitForSingleObject(sleepTimer.get(), INFINITE) != WAIT_OBJECT_0)
{
return -1;
}
return 0;
#endif
}
//-----------------------------------------------------------------------------
//
// Description: Get the number of processors
//
int OpenThreads::GetNumberOfProcessors()
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwNumberOfProcessors;
}
int OpenThreads::SetProcessorAffinityOfCurrentThread(unsigned int cpunum)
{
if (cpunum<0) return -1;
Thread::Init();
Thread* thread = Thread::CurrentThread();
if (thread)
{
return thread->setProcessorAffinity(cpunum);
}
else
{
// non op right now, needs implementation.
return -1;
}
}

View File

@ -0,0 +1,149 @@
/* -*-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.
*/
//
// Win32Barrier.c++ - C++ Barrier class built on top of POSIX threads.
// ~~~~~~~~~~~~~~~~~~
//
#include <OpenThreads/Barrier>
#include <OpenThreads/Thread>
#include <OpenThreads/ScopedLock>
#include "Win32BarrierPrivateData.h"
using namespace OpenThreads;
// so compiler can place it somewhere
Win32BarrierPrivateData::~Win32BarrierPrivateData()
{
};
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Barrier::Barrier(int numThreads) {
Win32BarrierPrivateData *pd = new Win32BarrierPrivateData();
pd->cnt = 0;
pd->phase = 0;
pd->maxcnt = numThreads;
_valid = true;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Barrier::~Barrier() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
delete pd;
}
//----------------------------------------------------------------------------
//
// Description: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
pd->cnt = 0;
pd->phase = 0;
}
//----------------------------------------------------------------------------
//
// Description: Block until numThreads threads have entered the barrier.
//
// Use: public.
//
void Barrier::block(unsigned int numThreads) {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_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) { // I am the last one
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->cond.broadcast();
}else{
while (pd->phase == my_phase ) {
pd->cond.wait(&pd->lock);
}
}
}
}
void Barrier::invalidate()
{
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
pd->lock.lock();
_valid = false;
pd->lock.unlock();
release();
}
//----------------------------------------------------------------------------
//
// Description: Release the barrier, now.
//
// Use: public.
//
void Barrier::release() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
int my_phase;
ScopedLock<Mutex> lock(pd->lock);
my_phase = pd->phase;
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->cond.broadcast();
}
//----------------------------------------------------------------------------
//
// Description: Return the number of threads currently blocked in the barrier
//
// Use: public
//
int Barrier::numThreadsCurrentlyBlocked() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
int numBlocked = -1;
ScopedLock<Mutex> lock(pd->lock);
numBlocked = pd->cnt;
return numBlocked;
}

View File

@ -0,0 +1,95 @@
/* -*-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.
*/
//
// Win32PrivateData.h - Private data structure for Thread
// ~~~~~~~~~~~~~~~~~~~~~
#ifndef _Win32PRIVATEDATA_H_
#define _Win32PRIVATEDATA_H_
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0400
#include <windows.h>
#endif
#include <OpenThreads/Thread>
#include <OpenThreads/Block>
#include "HandleHolder.h"
namespace OpenThreads {
class Win32ThreadPrivateData {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can use our data.
//
friend class Thread;
//-------------------------------------------------------------------------
// We're friendly to Win32PrivateActions, so it can get at some
// variables.
//
friend class ThreadPrivateActions;
private:
Win32ThreadPrivateData() {};
~Win32ThreadPrivateData();
size_t stackSize;
bool isRunning;
Block threadStartedBlock;
int cancelMode; // 0 - deffered (default) 1-asynch 2-disabled
bool detached;
Thread::ThreadPriority threadPriority;
Thread::ThreadPolicy threadPolicy;
HandleHolder tid;
int uniqueId;
public:
HandleHolder cancelEvent;
struct TlsHolder{ // thread local storage slot
DWORD ID;
TlsHolder(): ID(TlsAlloc()){
}
~TlsHolder(){
TlsFree(ID);
}
};
static TlsHolder TLS;
};
DWORD cooperativeWait(HANDLE waitHandle, unsigned long timeout);
}
#endif // !_PTHREADPRIVATEDATA_H_