Initial source commit
This commit is contained in:
commit
f1384c11ee
335 changed files with 52715 additions and 0 deletions
79
minorGems/system/BinarySemaphore.h
Normal file
79
minorGems/system/BinarySemaphore.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Fixed a bug in the precompiler directives.
|
||||
*
|
||||
* 2003-August-26 Jason Rohrer
|
||||
* Added support for timeouts on wait.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef BINARY_SEMAPHORE_CLASS_INCLUDED
|
||||
#define BINARY_SEMAPHORE_CLASS_INCLUDED
|
||||
|
||||
#include "MutexLock.h"
|
||||
|
||||
/**
|
||||
* Binary semaphore class. Semaphore starts out with a value of 0.
|
||||
*
|
||||
* Note: Implementation for the functions defined here is provided
|
||||
* separately for each platform (in the mac/ linux/ and win32/
|
||||
* subdirectories).
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class BinarySemaphore {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a binary semaphore.
|
||||
*/
|
||||
BinarySemaphore();
|
||||
|
||||
~BinarySemaphore();
|
||||
|
||||
|
||||
/**
|
||||
* Blocks on this semaphore until signal() is called by another thread.
|
||||
* Note that if signal() has already been called before wait() is
|
||||
* called, then this call will return immediately, though the semaphore
|
||||
* is reset to 0 by this call.
|
||||
*
|
||||
* @param inTimeoutInMilliseconds the maximum time to wait in
|
||||
* milliseconds, or -1 to wait forever. Defaults to -1.
|
||||
*
|
||||
* @return 1 if the semaphore was signaled, or 0 if it timed out.
|
||||
*/
|
||||
int wait( int inTimeoutInMilliseconds = -1 );
|
||||
|
||||
|
||||
/**
|
||||
* Signals the semaphore, allowing a waiting thread to return from
|
||||
* its call to wait(). (The semaphore is set to 1 by this call if
|
||||
* no thread is waiting on the semaphore currently.)
|
||||
*/
|
||||
void signal();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// starts at 0
|
||||
int mSemaphoreValue;
|
||||
|
||||
/**
|
||||
* Used by platform-specific implementations.
|
||||
*/
|
||||
void *mNativeObjectPointerA;
|
||||
void *mNativeObjectPointerB;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
59
minorGems/system/FinishedSignalThread.cpp
Normal file
59
minorGems/system/FinishedSignalThread.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-March-9 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-March-11 Jason Rohrer
|
||||
* Changed so that destructor joins thread.
|
||||
*
|
||||
* 2002-April-4 Jason Rohrer
|
||||
* Changed name of lock to avoid confusion with subclass-provided locks.
|
||||
*
|
||||
* 2002-August-5 Jason Rohrer
|
||||
* Fixed member initialization order to match declaration order.
|
||||
*
|
||||
* 2004-April-1 Jason Rohrer
|
||||
* Moved from konspire2b into minorGems.
|
||||
* Changed so that destructor does not join the thread.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "FinishedSignalThread.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
FinishedSignalThread::FinishedSignalThread()
|
||||
: mFinishedLock( new MutexLock() ), mFinished( false ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
FinishedSignalThread::~FinishedSignalThread() {
|
||||
|
||||
delete mFinishedLock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char FinishedSignalThread::isFinished() {
|
||||
mFinishedLock->lock();
|
||||
char finished = mFinished;
|
||||
mFinishedLock->unlock();
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FinishedSignalThread::setFinished() {
|
||||
mFinishedLock->lock();
|
||||
mFinished = true;
|
||||
mFinishedLock->unlock();
|
||||
}
|
||||
|
100
minorGems/system/FinishedSignalThread.h
Normal file
100
minorGems/system/FinishedSignalThread.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-March-9 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-March-10 Jason Rohrer
|
||||
* Made destructor public.
|
||||
*
|
||||
* 2002-March-11 Jason Rohrer
|
||||
* Changed so that destructor joins thread.
|
||||
*
|
||||
* 2002-April-4 Jason Rohrer
|
||||
* Changed name of lock to avoid confusion with subclass-provided locks.
|
||||
*
|
||||
* 2004-April-1 Jason Rohrer
|
||||
* Moved from konspire2b into minorGems.
|
||||
* Changed so that destructor does not join the thread.
|
||||
*
|
||||
* 2004-November-19 Jason Rohrer
|
||||
* Changed to virtual inheritance from Thread class.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef FINISHED_SIGNAL_THREAD_INCLUDED
|
||||
#define FINISHED_SIGNAL_THREAD_INCLUDED
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/Thread.h"
|
||||
#include "minorGems/system/MutexLock.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Abstract subclass if thread that has a
|
||||
* synchronized finished signal.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class FinishedSignalThread : public virtual Thread {
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Only destroys this thread.
|
||||
* Does not join.
|
||||
*/
|
||||
virtual ~FinishedSignalThread();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether this thread is finished and
|
||||
* ready to be destroyed.
|
||||
*
|
||||
* @return true iff this thread is finished.
|
||||
*/
|
||||
char isFinished();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
FinishedSignalThread();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets that this thread is finished and
|
||||
* ready to be destroyed.
|
||||
*
|
||||
* For this class to work properly, the subclass
|
||||
* MUST call this function at the end of its run method.
|
||||
*/
|
||||
void setFinished();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
MutexLock *mFinishedLock;
|
||||
|
||||
char mFinished;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
116
minorGems/system/FinishedSignalThreadManager.cpp
Normal file
116
minorGems/system/FinishedSignalThreadManager.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2004-November-9 Jason Rohrer
|
||||
* Created.
|
||||
* Modified from MUTE's ChannelReceivingThreadManager.
|
||||
*
|
||||
* 2005-January-9 Jason Rohrer
|
||||
* Changed to sleep on a semaphore to allow sleep to be interrupted.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/FinishedSignalThreadManager.h"
|
||||
|
||||
|
||||
|
||||
FinishedSignalThreadManager::FinishedSignalThreadManager()
|
||||
: mLock( new MutexLock() ),
|
||||
mThreadVector( new SimpleVector<FinishedSignalThread *>() ),
|
||||
mStopSignal( false ),
|
||||
mSleepSemaphore( new BinarySemaphore() ) {
|
||||
|
||||
this->start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
FinishedSignalThreadManager::~FinishedSignalThreadManager() {
|
||||
mLock->lock();
|
||||
mStopSignal = true;
|
||||
mLock->unlock();
|
||||
|
||||
// signal the sleeping semaphore to wake up the thread
|
||||
mSleepSemaphore->signal();
|
||||
|
||||
this->join();
|
||||
|
||||
mLock->lock();
|
||||
|
||||
// destroy all remaining threads
|
||||
int numThreads = mThreadVector->size();
|
||||
|
||||
for( int i=0; i<numThreads; i++ ) {
|
||||
delete *( mThreadVector->getElement( i ) );
|
||||
}
|
||||
delete mThreadVector;
|
||||
|
||||
|
||||
mLock->unlock();
|
||||
delete mLock;
|
||||
|
||||
delete mSleepSemaphore;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FinishedSignalThreadManager::addThread(
|
||||
FinishedSignalThread *inThread ) {
|
||||
|
||||
mLock->lock();
|
||||
|
||||
mThreadVector->push_back( inThread );
|
||||
|
||||
mLock->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FinishedSignalThreadManager::run() {
|
||||
|
||||
char stopped;
|
||||
|
||||
mLock->lock();
|
||||
stopped = mStopSignal;
|
||||
mLock->unlock();
|
||||
|
||||
|
||||
while( !stopped ) {
|
||||
// wait for 10 seconds
|
||||
int wasSignaled = mSleepSemaphore->wait( 10000 );
|
||||
|
||||
if( wasSignaled == 1 ) {
|
||||
// signaled... we should stop
|
||||
return;
|
||||
}
|
||||
|
||||
char foundFinished = true;
|
||||
|
||||
while( foundFinished ) {
|
||||
foundFinished = false;
|
||||
|
||||
mLock->lock();
|
||||
|
||||
int numThreads = mThreadVector->size();
|
||||
|
||||
for( int i=0; i<numThreads && !foundFinished; i++ ) {
|
||||
|
||||
FinishedSignalThread *currentThread =
|
||||
*( mThreadVector->getElement( i ) );
|
||||
|
||||
if( currentThread->isFinished() ) {
|
||||
delete currentThread;
|
||||
mThreadVector->deleteElement( i );
|
||||
foundFinished = true;
|
||||
}
|
||||
}
|
||||
mLock->unlock();
|
||||
}
|
||||
|
||||
mLock->lock();
|
||||
stopped = mStopSignal;
|
||||
mLock->unlock();
|
||||
}
|
||||
}
|
||||
|
82
minorGems/system/FinishedSignalThreadManager.h
Normal file
82
minorGems/system/FinishedSignalThreadManager.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2004-November-9 Jason Rohrer
|
||||
* Created.
|
||||
* Modified from MUTE's ChannelReceivingThreadManager.
|
||||
*
|
||||
* 2005-January-9 Jason Rohrer
|
||||
* Changed to sleep on a semaphore to allow sleep to be interrupted.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED
|
||||
#define FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/FinishedSignalThread.h"
|
||||
|
||||
#include "minorGems/util/SimpleVector.h"
|
||||
#include "minorGems/system/Thread.h"
|
||||
#include "minorGems/system/MutexLock.h"
|
||||
#include "minorGems/system/BinarySemaphore.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A thread that manages the destruction of FinishedSignalThreads.
|
||||
*
|
||||
* @author Jason Rohrer.
|
||||
*/
|
||||
class FinishedSignalThreadManager : public Thread {
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs and starts this manager.
|
||||
*/
|
||||
FinishedSignalThreadManager();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Stops and destroys this manager.
|
||||
*/
|
||||
~FinishedSignalThreadManager();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a thread to this manager.
|
||||
*
|
||||
* @param inThread the thread to add.
|
||||
* Will be destroyed by this class.
|
||||
*/
|
||||
void addThread( FinishedSignalThread *inThread );
|
||||
|
||||
|
||||
|
||||
// implements the Thread interface
|
||||
void run();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
MutexLock *mLock;
|
||||
|
||||
SimpleVector<FinishedSignalThread *> *mThreadVector;
|
||||
|
||||
char mStopSignal;
|
||||
|
||||
BinarySemaphore *mSleepSemaphore;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
51
minorGems/system/Launcher.h
Normal file
51
minorGems/system/Launcher.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-10 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef LAUNCHER_INCLUDED
|
||||
#define LAUNCHER_INCLUDED
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for launching processes.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class Launcher {
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Launches a command in a new process.
|
||||
*
|
||||
* @param inCommandName the name of the command to launch.
|
||||
* Must be destroyed by caller if non-const.
|
||||
* @param inArguments an array of argument strings for the command.
|
||||
* This array must be terminated by a NULL pointer.
|
||||
* Note that by convention, the first argument should be the
|
||||
* command name.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
static void launchCommand( char *inCommandName,
|
||||
char **inArguments );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
71
minorGems/system/MutexLock.h
Normal file
71
minorGems/system/MutexLock.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-March-29 Jason Rohrer
|
||||
* Added Fortify inclusion.
|
||||
*
|
||||
* 2002-October-18 Jason Rohrer
|
||||
* Moved common include out of header and into platform-specific cpp files,
|
||||
* since MemoryTrack uses a mutex lock.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef MUTEX_LOCK_CLASS_INCLUDED
|
||||
#define MUTEX_LOCK_CLASS_INCLUDED
|
||||
|
||||
|
||||
|
||||
#ifdef FORTIFY
|
||||
#include "minorGems/util/development/fortify/fortify.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mutex lock class.
|
||||
*
|
||||
* Note: Implementation for the functions defined here is provided
|
||||
* separately for each platform (in the mac/ linux/ and win32/
|
||||
* subdirectories).
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class MutexLock {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a mutex lock;
|
||||
*/
|
||||
MutexLock();
|
||||
|
||||
~MutexLock();
|
||||
|
||||
|
||||
/**
|
||||
* Locks the mutex. Blocks until mutex available if it's
|
||||
* already locked by another thread.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* Unlocks the mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Used by platform-specific implementations.
|
||||
*/
|
||||
void *mNativeObjectPointer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
201
minorGems/system/Semaphore.h
Normal file
201
minorGems/system/Semaphore.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Added a willBlock() function.
|
||||
*
|
||||
* 2001-February-24 Jason Rohrer
|
||||
* Fixed incorrect delete usage.
|
||||
*
|
||||
* 2002-February-11 Jason Rohrer
|
||||
* Fixed a mistake in the signal() comment.
|
||||
*
|
||||
* 2003-August-26 Jason Rohrer
|
||||
* Added support for timeouts on wait.
|
||||
*
|
||||
* 2003-December-28 Jason Rohrer
|
||||
* Fixed a bug in semaphore value when we timeout on wait.
|
||||
*
|
||||
* 2004-January-9 Jason Rohrer
|
||||
* Fixed a preprocessor error.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef SEMAPHORE_CLASS_INCLUDED
|
||||
#define SEMAPHORE_CLASS_INCLUDED
|
||||
|
||||
#include "MutexLock.h"
|
||||
#include "BinarySemaphore.h"
|
||||
|
||||
|
||||
/**
|
||||
* General semaphore with an unbounded value.
|
||||
*
|
||||
* This class uses BinarySemaphores to implement general semaphores,
|
||||
* so it relies on platform-specific BinarySemaphore implementations,
|
||||
* but this class itself is platform-independent.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class Semaphore {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a semaphore.
|
||||
*
|
||||
* @param inStartingValue the starting value for this semaphore.
|
||||
* Defaults to 0 if unspecified.
|
||||
*/
|
||||
Semaphore( int inStartingValue = 0 );
|
||||
|
||||
~Semaphore();
|
||||
|
||||
|
||||
/**
|
||||
* If this semaphore's current value is 0, then this call blocks
|
||||
* on this semaphore until signal() is called by another thread.
|
||||
* If this semaphore's value is >0, then it is decremented by this
|
||||
* call.
|
||||
*
|
||||
* @param inTimeoutInMilliseconds the maximum time to wait in
|
||||
* milliseconds, or -1 to wait forever. Defaults to -1.
|
||||
*
|
||||
* @return 1 if the semaphore was signaled, or 0 if it timed out.
|
||||
*/
|
||||
int wait( int inTimeoutInMilliseconds = -1 );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If a thread is waiting on this semaphore, then the thread
|
||||
* becomes unblocked.
|
||||
* If no thread is waiting, then the semaphore is incremented.
|
||||
*/
|
||||
void signal();
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if a call to wait would have blocked.
|
||||
*/
|
||||
char willBlock();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// starts at 0
|
||||
int mSemaphoreValue;
|
||||
|
||||
// mutex semaphore starts at 1
|
||||
BinarySemaphore *mMutexSemaphore;
|
||||
// blocking semaphore starts at 0
|
||||
BinarySemaphore *mBlockingSemaphore;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline Semaphore::Semaphore( int inStartingValue )
|
||||
: mSemaphoreValue( inStartingValue ),
|
||||
mMutexSemaphore( new BinarySemaphore() ),
|
||||
mBlockingSemaphore( new BinarySemaphore() ) {
|
||||
|
||||
// increment the mutex semaphore to 1
|
||||
mMutexSemaphore->signal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Semaphore::~Semaphore() {
|
||||
delete mMutexSemaphore;
|
||||
delete mBlockingSemaphore;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline int Semaphore::wait( int inTimeoutInMilliseconds ) {
|
||||
int returnValue;
|
||||
// this implementation copied from _Operating System Concepts_, p. 172
|
||||
|
||||
// lock the mutex
|
||||
mMutexSemaphore->wait();
|
||||
// decrement the semaphore
|
||||
mSemaphoreValue--;
|
||||
if( mSemaphoreValue < 0 ) {
|
||||
// we should block
|
||||
|
||||
// release the mutex
|
||||
mMutexSemaphore->signal();
|
||||
|
||||
// block
|
||||
returnValue = mBlockingSemaphore->wait( inTimeoutInMilliseconds );
|
||||
|
||||
if( returnValue != 1 ) {
|
||||
// timed out
|
||||
|
||||
// increment the semaphore, since we never got signaled
|
||||
// lock the mutex
|
||||
mMutexSemaphore->wait();
|
||||
mSemaphoreValue++;
|
||||
|
||||
// we will unlock the mutex below
|
||||
}
|
||||
}
|
||||
else {
|
||||
returnValue = 1;
|
||||
}
|
||||
|
||||
// release the mutex
|
||||
// ( if we were signaled, then the signaller left the mutex locked )
|
||||
// ( if we timed out, then we re-locked the mutex above )
|
||||
mMutexSemaphore->signal();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char Semaphore::willBlock() {
|
||||
char returnValue = false;
|
||||
|
||||
// lock the mutex
|
||||
mMutexSemaphore->wait();
|
||||
|
||||
// check if we will block
|
||||
if( mSemaphoreValue <= 0 ) {
|
||||
returnValue = true;
|
||||
}
|
||||
|
||||
// release the mutex
|
||||
mMutexSemaphore->signal();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Semaphore::signal() {
|
||||
// lock the mutex
|
||||
mMutexSemaphore->wait();
|
||||
// increment the semaphore
|
||||
mSemaphoreValue++;
|
||||
if( mSemaphoreValue <= 0 ) {
|
||||
// we need to wake up a waiting thread
|
||||
mBlockingSemaphore->signal();
|
||||
// let the waiting thread unlock the mutex
|
||||
}
|
||||
else {
|
||||
// no threads are waiting, so we need to unlock the mutex
|
||||
mMutexSemaphore->signal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
65
minorGems/system/StopSignalThread.cpp
Normal file
65
minorGems/system/StopSignalThread.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-April-4 Jason Rohrer
|
||||
* Created.
|
||||
* Changed to reflect the fact that the base class
|
||||
* destructor is called *after* the derived class destructor.
|
||||
*
|
||||
* 2002-August-5 Jason Rohrer
|
||||
* Fixed member initialization order to match declaration order.
|
||||
*
|
||||
* 2003-September-5 Jason Rohrer
|
||||
* Moved into minorGems.
|
||||
*
|
||||
* 2005-January-9 Jason Rohrer
|
||||
* Changed to sleep on a semaphore to make sleep interruptable by stop.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "StopSignalThread.h"
|
||||
|
||||
|
||||
|
||||
StopSignalThread::StopSignalThread()
|
||||
: mStopLock( new MutexLock() ), mStopped( false ),
|
||||
mSleepSemaphore( new BinarySemaphore() ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
StopSignalThread::~StopSignalThread() {
|
||||
|
||||
delete mStopLock;
|
||||
delete mSleepSemaphore;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void StopSignalThread::sleep( unsigned long inTimeInMilliseconds ) {
|
||||
mSleepSemaphore->wait( inTimeInMilliseconds );
|
||||
}
|
||||
|
||||
|
||||
|
||||
char StopSignalThread::isStopped() {
|
||||
mStopLock->lock();
|
||||
char stoped = mStopped;
|
||||
mStopLock->unlock();
|
||||
|
||||
return stoped;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void StopSignalThread::stop() {
|
||||
mStopLock->lock();
|
||||
mStopped = true;
|
||||
mStopLock->unlock();
|
||||
|
||||
// signal the semaphore to wake up the thread, if it is sleeping
|
||||
mSleepSemaphore->signal();
|
||||
}
|
||||
|
104
minorGems/system/StopSignalThread.h
Normal file
104
minorGems/system/StopSignalThread.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-April-4 Jason Rohrer
|
||||
* Created.
|
||||
* Changed to reflect the fact that the base class
|
||||
* destructor is called *after* the derived class destructor.
|
||||
*
|
||||
* 2003-September-5 Jason Rohrer
|
||||
* Moved into minorGems.
|
||||
*
|
||||
* 2004-November-19 Jason Rohrer
|
||||
* Changed to virtual inheritance from Thread class.
|
||||
*
|
||||
* 2005-January-9 Jason Rohrer
|
||||
* Changed to sleep on a semaphore to make sleep interruptable by stop.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef STOP_SIGNAL_THREAD_INCLUDED
|
||||
#define STOP_SIGNAL_THREAD_INCLUDED
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/Thread.h"
|
||||
#include "minorGems/system/MutexLock.h"
|
||||
#include "minorGems/system/BinarySemaphore.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Abstract subclass of thread that has a stop signal.
|
||||
*
|
||||
* Note that subclasses MUST check the isStopped() function
|
||||
* periodically in their run() function for this class to work
|
||||
* properly.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class StopSignalThread : public virtual Thread {
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Only destroys this thread.
|
||||
* Does not stop or join.
|
||||
*/
|
||||
virtual ~StopSignalThread();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
StopSignalThread();
|
||||
|
||||
|
||||
|
||||
// overrides Thread::sleep to make it interruptable by our stop call
|
||||
virtual void sleep( unsigned long inTimeInMilliseconds );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Signals this thread to stop, interrupting it if it is sleeping.
|
||||
*
|
||||
* Thread safe.
|
||||
*
|
||||
* Thread must be joined after this call returns.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether this thread has been signaled to stop.
|
||||
*
|
||||
* Thread safe.
|
||||
*
|
||||
* @return true if this thread should stop.
|
||||
*/
|
||||
char isStopped();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
MutexLock *mStopLock;
|
||||
char mStopped;
|
||||
|
||||
BinarySemaphore *mSleepSemaphore;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
54
minorGems/system/TestThread.cpp
Normal file
54
minorGems/system/TestThread.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-November-14 Jason Rohrer
|
||||
* Added more verbose printouts.
|
||||
*
|
||||
* 2004-March-31 Jason Rohrer
|
||||
* Added test of detached threads.
|
||||
*/
|
||||
|
||||
#include "TestThread.h"
|
||||
|
||||
int numToCount = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* Main method that spawns two TestThreads.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
int main() {
|
||||
|
||||
TestThread *thread1 = new TestThread( 1, numToCount );
|
||||
TestThread *thread2 = new TestThread( 2, numToCount );
|
||||
TestThread *thread3 = new TestThread( 3, numToCount );
|
||||
|
||||
|
||||
ThreadSafePrinter::printf( "Starting thread 1\n" );
|
||||
thread1->start();
|
||||
ThreadSafePrinter::printf( "Starting thread 2\n" );
|
||||
thread2->start();
|
||||
ThreadSafePrinter::printf( "Starting thread 3 in detached mode\n" );
|
||||
thread3->start( true );
|
||||
|
||||
Thread::sleep( 5000 );
|
||||
|
||||
ThreadSafePrinter::printf( "Joining thread 1\n" );
|
||||
thread1->join();
|
||||
ThreadSafePrinter::printf( "Joining thread 2\n" );
|
||||
thread2->join();
|
||||
|
||||
ThreadSafePrinter::printf( "Destroying thread 1\n" );
|
||||
delete thread1;
|
||||
ThreadSafePrinter::printf( "Destroying thread 2\n" );
|
||||
delete thread2;
|
||||
|
||||
ThreadSafePrinter::printf(
|
||||
"Thread 3 should handle its own destruction.\n" );
|
||||
|
||||
return 0;
|
||||
}
|
77
minorGems/system/TestThread.h
Normal file
77
minorGems/system/TestThread.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Switched to a ThreadSafePrinter in attempt to get it to work on Win32.
|
||||
* Changed print call to printf.
|
||||
*
|
||||
* 2002-November-14 Jason Rohrer
|
||||
* Added missing destructor.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef TEST_THREAD_CLASS_INCLUDED
|
||||
#define TEST_THREAD_CLASS_INCLUDED
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
#include "ThreadSafePrinter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* Test subclass of Thread class. Useful for testing if platform-specific
|
||||
* thread implmentations are working.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class TestThread : public Thread {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a test thread and tells it how high to count to.
|
||||
*
|
||||
* @param inID id number thread will print along with count.
|
||||
* @param inNumToCount thread will count from 0 to this number.
|
||||
*/
|
||||
TestThread( int inID, int inNumToCount );
|
||||
|
||||
~TestThread();
|
||||
|
||||
// override the run method from PThread
|
||||
void run();
|
||||
|
||||
private:
|
||||
int mID;
|
||||
int mNumToCount;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline TestThread::TestThread( int inID, int inNumToCount )
|
||||
: mID( inID ), mNumToCount( inNumToCount ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline TestThread::~TestThread() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void TestThread::run() {
|
||||
for( int i=0; i<=mNumToCount; i++ ) {
|
||||
ThreadSafePrinter::printf( "Thread %d counting %d.\n", mID, i );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
136
minorGems/system/Thread.h
Normal file
136
minorGems/system/Thread.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-March-4 Jason Rohrer
|
||||
* Made sleep() static so it can be called by non-Thread classes.
|
||||
*
|
||||
* 2001-May-12 Jason Rohrer
|
||||
* Added comments about joining before destroying.
|
||||
*
|
||||
* 2002-March-29 Jason Rohrer
|
||||
* Added Fortify inclusion.
|
||||
*
|
||||
* 2002-August-5 Jason Rohrer
|
||||
* Made destructor virtual.
|
||||
*
|
||||
* 2004-March-31 Jason Rohrer
|
||||
* Added support for detatched mode.
|
||||
*
|
||||
* 2005-January-9 Jason Rohrer
|
||||
* Made sleep function virtual to allow overrides.
|
||||
*
|
||||
* 2005-January-22 Jason Rohrer
|
||||
* Added a static sleep function.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef THREAD_CLASS_INCLUDED
|
||||
#define THREAD_CLASS_INCLUDED
|
||||
|
||||
|
||||
|
||||
#ifdef FORTIFY
|
||||
#include "minorGems/util/development/fortify/fortify.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class to be subclassed by all threads.
|
||||
*
|
||||
* Note: Implementation for the functions defined here is provided
|
||||
* separately for each platform (in the mac/ linux/ and win32/
|
||||
* subdirectories).
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class Thread {
|
||||
|
||||
public:
|
||||
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
|
||||
|
||||
/**
|
||||
* Starts this Thread.
|
||||
*
|
||||
* Note that after starting a non-detached thread, it _must_ be
|
||||
* joined before being destroyed to avoid memory leaks.
|
||||
*
|
||||
* Threads running in detatched mode handle their own destruction
|
||||
* as they terminate and do not need to be joined at all.
|
||||
*
|
||||
* @param inDetach true if this thread should run in detatched mode,
|
||||
* or false to run in non-detached mode. Defaults to false.
|
||||
*/
|
||||
void start( char inDetach = false );
|
||||
|
||||
|
||||
/**
|
||||
* To be overriden by subclasses.
|
||||
* This method will be run by the Thread after start() has been called.
|
||||
*/
|
||||
virtual void run() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Blocks until this thread finishes executing its run() method.
|
||||
*
|
||||
* Must be called before destroying this thread, if this thread
|
||||
* has been started.
|
||||
*/
|
||||
void join();
|
||||
|
||||
|
||||
/**
|
||||
* Puts the current thread to sleep for a specified amount of time.
|
||||
*
|
||||
* Note that given a thread instance threadA, calling threadA.sleep()
|
||||
* will put the calling thread to sleep.
|
||||
*
|
||||
* @param inTimeInMilliseconds the number of milliseconds to sleep.
|
||||
*/
|
||||
virtual void sleep( unsigned long inTimeInMilliseconds ) {
|
||||
staticSleep( inTimeInMilliseconds );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Same as sleep, but can be called without constructing a thread.
|
||||
*/
|
||||
static void staticSleep( unsigned long inTimeInMilliseconds );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether this thread is detached.
|
||||
*
|
||||
* @return true if this thread is detached.
|
||||
*/
|
||||
char isDetatched() {
|
||||
return mIsDetached;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Used by platform-specific implementations.
|
||||
*/
|
||||
void *mNativeObjectPointer;
|
||||
|
||||
|
||||
char mIsDetached;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
71
minorGems/system/ThreadSafePrinter.h
Normal file
71
minorGems/system/ThreadSafePrinter.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-October-14 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Converted to use MutexLock and added to minorGems source tree.
|
||||
* Changed tprintf to be static (the mutexes don't work otherwise).
|
||||
* Now we're closing the argument list.
|
||||
* Fixed so that it works with any number of arguments.
|
||||
* Changed name of print function to printf.
|
||||
*
|
||||
* 2004-March-31 Jason Rohrer
|
||||
* Fixed static memory leak.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef THREAD_SAFE_PRINTER_INCLUDED
|
||||
#define THREAD_SAFE_PRINTER_INCLUDED
|
||||
|
||||
#include "MutexLock.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// for variable argument lists
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Thread safe printf function. Note that printf is actually thread safe
|
||||
* anyway, so this is just to demonstrate and test locks. It seems as
|
||||
* though printf _isn't_ thread safe on certain platforms, so this class
|
||||
* may be useful.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class ThreadSafePrinter {
|
||||
|
||||
public:
|
||||
|
||||
static int printf( const char* inFormatString, ... );
|
||||
|
||||
private:
|
||||
static MutexLock sLock;
|
||||
|
||||
};
|
||||
|
||||
// initialize static members
|
||||
MutexLock ThreadSafePrinter::sLock;
|
||||
|
||||
inline int ThreadSafePrinter::printf( const char*inFormatString, ... ) {
|
||||
|
||||
va_list argList;
|
||||
va_start( argList, inFormatString );
|
||||
|
||||
sLock.lock();
|
||||
|
||||
int returnVal = vprintf( inFormatString, argList );
|
||||
fflush( stdout );
|
||||
|
||||
sLock.unlock();
|
||||
|
||||
va_end( argList );
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
112
minorGems/system/Time.h
Normal file
112
minorGems/system/Time.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-October-29 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2004-October-14 Jason Rohrer
|
||||
* Fixed sign bug.
|
||||
*
|
||||
* 2005-February-10 Jason Rohrer
|
||||
* Added function to get time in floating point format.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef TIME_INCLUDED
|
||||
#define TIME_INCLUDED
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for platform-independent, high-resolution time access.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class Time {
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current time in seconds and milliseconds.
|
||||
*
|
||||
* No guarentee about when absolute 0 of this time
|
||||
* scale is for particular systems.
|
||||
*
|
||||
* @param outSeconds pointer to where the time in seconds
|
||||
* will be returned.
|
||||
* @param outMilliseconds pointer to where the extra
|
||||
* milliseconds will be returned. Value returned is in [0,999].
|
||||
*/
|
||||
static void getCurrentTime( unsigned long *outSeconds,
|
||||
unsigned long *outMilliseconds );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current time in fractional (double) seconds.
|
||||
*
|
||||
* @return the current time in seconds.
|
||||
*/
|
||||
static double getCurrentTime();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of milliseconds that have passed
|
||||
* since a time in seconds and milliseconds.
|
||||
*
|
||||
* @param inSeconds the start time, in seconds.
|
||||
* @param inMilliseconds the start time's additional milliseconds.
|
||||
*
|
||||
* @return the number of milliseconds that have passed
|
||||
* since inSeconds:inMilliseconds. May overflow if
|
||||
* more than 49 days have passed (assuming 32-bit longs).
|
||||
*/
|
||||
static unsigned long getMillisecondsSince(
|
||||
unsigned long inSeconds, unsigned long inMilliseconds );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline double Time::getCurrentTime() {
|
||||
unsigned long currentTimeS;
|
||||
unsigned long currentTimeMS;
|
||||
getCurrentTime( ¤tTimeS, ¤tTimeMS );
|
||||
|
||||
return currentTimeS + currentTimeMS / 1000.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline unsigned long Time::getMillisecondsSince(
|
||||
unsigned long inSeconds, unsigned long inMilliseconds ) {
|
||||
|
||||
unsigned long currentTimeS;
|
||||
unsigned long currentTimeMS;
|
||||
getCurrentTime( ¤tTimeS, ¤tTimeMS );
|
||||
|
||||
|
||||
unsigned long deltaS = ( currentTimeS - inSeconds );
|
||||
long deltaMS = ( (long)currentTimeMS - (long)inMilliseconds );
|
||||
|
||||
// carry, if needed
|
||||
if( deltaMS < 0 ) {
|
||||
deltaS--;
|
||||
deltaMS += 1000;
|
||||
}
|
||||
|
||||
return 1000 * deltaS + deltaMS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
108
minorGems/system/endian.h
Normal file
108
minorGems/system/endian.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-May-25 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2004-January-12 Jason Rohrer
|
||||
* Added support for metrowerks win32 compiler.
|
||||
*
|
||||
* 2009-April-3 Jason Rohrer
|
||||
* OpenBSD support.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Include this file to define __BYTE_ORDER
|
||||
*
|
||||
* After this has been included, __BYTE_ORDER will be either
|
||||
* __LITTLE_ENDIAN or
|
||||
* __BIG_ENDIAN
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <machine/endian.h>
|
||||
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <machine/endian.h>
|
||||
|
||||
|
||||
// default BSD case
|
||||
#elif defined(BSD)
|
||||
#include <machine/endian.h>
|
||||
|
||||
|
||||
|
||||
#elif defined(SOLARIS)
|
||||
// Code for Solaris defs adapted from:
|
||||
// MD5 message-digest algorithm.
|
||||
// by Colin Plumb in 1993, no copyright is claimed.
|
||||
|
||||
//each solaris is different -- this won't work on 2.6 or 2.7
|
||||
# include <sys/isa_defs.h>
|
||||
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
|
||||
#ifdef _LITTLE_ENDIAN
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
#else // default to big endian
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
// end solaris case
|
||||
|
||||
|
||||
|
||||
#elif defined(WIN_32) || \
|
||||
( defined(__MWERKS__) && defined(__INTEL__) ) // windows case
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
// end windows case
|
||||
|
||||
|
||||
|
||||
#else
|
||||
// linux case
|
||||
#include <endian.h>
|
||||
|
||||
// end linux case
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
// end of all system-specific cases
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// BSD calls it BYTE_ORDER, linux calls it __BYTE_ORDER
|
||||
#ifndef __BYTE_ORDER
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
192
minorGems/system/linux/BinarySemaphoreLinux.cpp
Normal file
192
minorGems/system/linux/BinarySemaphoreLinux.cpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2003-August-26 Jason Rohrer
|
||||
* Added support for timeouts on wait.
|
||||
*
|
||||
* 2006-February-28 Jason Rohrer
|
||||
* Fixed bug in sub-second timeout computation.
|
||||
*/
|
||||
|
||||
#include "minorGems/system/BinarySemaphore.h"
|
||||
#include "minorGems/system/Time.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
/**
|
||||
* Linux-specific implementation of the BinarySemaphore class member functions.
|
||||
*
|
||||
* May also be compatible with other POSIX-like systems.
|
||||
*
|
||||
* To compile:
|
||||
* g++ -lpthread
|
||||
*/
|
||||
|
||||
/**
|
||||
* Native object pointer A is the condition variable.
|
||||
* Pointer B is the mutex that must go along with it.
|
||||
*/
|
||||
|
||||
|
||||
BinarySemaphore::BinarySemaphore() :
|
||||
mSemaphoreValue( 0 ) {
|
||||
|
||||
// allocate a condition variable structure on the heap
|
||||
mNativeObjectPointerA = (void *)( new pthread_cond_t[1] );
|
||||
|
||||
// get a pointer to the cond
|
||||
pthread_cond_t *condPointer =
|
||||
(pthread_cond_t *)mNativeObjectPointerA;
|
||||
|
||||
// init the cond
|
||||
pthread_cond_init( &( condPointer[0] ), NULL );
|
||||
|
||||
|
||||
// allocate a mutex structure on the heap
|
||||
mNativeObjectPointerB = (void *)( new pthread_mutex_t[1] );
|
||||
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointerB;
|
||||
|
||||
// init the mutex
|
||||
pthread_mutex_init( &( mutexPointer[0] ), NULL );
|
||||
|
||||
}
|
||||
|
||||
BinarySemaphore::~BinarySemaphore() {
|
||||
|
||||
// get a pointer to the cond
|
||||
pthread_cond_t *condPointer =
|
||||
(pthread_cond_t *)mNativeObjectPointerA;
|
||||
|
||||
// destroy the cond
|
||||
pthread_cond_destroy( &( condPointer[0] ) );
|
||||
|
||||
// de-allocate the cond structure from the heap
|
||||
delete [] condPointer;
|
||||
|
||||
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointerB;
|
||||
|
||||
// destroy the mutex
|
||||
pthread_mutex_destroy( &( mutexPointer[0] ) );
|
||||
|
||||
// de-allocate the mutex structure from the heap
|
||||
delete [] mutexPointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int BinarySemaphore::wait( int inTimeoutInMilliseconds ) {
|
||||
|
||||
int returnValue = 1;
|
||||
|
||||
// get a pointer to the cond
|
||||
pthread_cond_t *condPointer =
|
||||
(pthread_cond_t *)mNativeObjectPointerA;
|
||||
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointerB;
|
||||
|
||||
|
||||
// lock the mutex
|
||||
pthread_mutex_lock( &( mutexPointer[0] ) );
|
||||
|
||||
if( mSemaphoreValue == 0 ) {
|
||||
// wait on condition variable, which automatically unlocks
|
||||
// the passed-in mutex
|
||||
|
||||
if( inTimeoutInMilliseconds == -1 ) {
|
||||
// no timeout
|
||||
pthread_cond_wait( &( condPointer[0] ), &( mutexPointer[0] ) );
|
||||
}
|
||||
else {
|
||||
// use timeout version
|
||||
|
||||
unsigned long nsecPerSecond = 1000000000;
|
||||
unsigned long nsecPerMillisecond = 1000000;
|
||||
|
||||
|
||||
unsigned long currentSec;
|
||||
unsigned long currentMS;
|
||||
|
||||
Time::getCurrentTime( ¤tSec, ¤tMS );
|
||||
|
||||
unsigned long currentNS = currentMS * nsecPerMillisecond;
|
||||
|
||||
|
||||
long timeoutSec = inTimeoutInMilliseconds / 1000;
|
||||
long extraMS = inTimeoutInMilliseconds % 1000;
|
||||
|
||||
long extraNS = extraMS * nsecPerMillisecond;
|
||||
|
||||
|
||||
|
||||
unsigned long absTimeoutSec = currentSec + timeoutSec;
|
||||
unsigned long absTimeoutNsec = currentNS + extraNS;
|
||||
|
||||
// check for nsec overflow
|
||||
if( absTimeoutNsec > nsecPerSecond ) {
|
||||
absTimeoutSec += 1;
|
||||
absTimeoutNsec -= nsecPerSecond;
|
||||
}
|
||||
|
||||
struct timespec abstime;
|
||||
abstime.tv_sec = absTimeoutSec;
|
||||
abstime.tv_nsec = absTimeoutNsec;
|
||||
|
||||
int result = pthread_cond_timedwait( &( condPointer[0] ),
|
||||
&( mutexPointer[0] ),
|
||||
&abstime );
|
||||
|
||||
if( result != 0 ) {
|
||||
// timed out
|
||||
returnValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// mutex is apparently re-locked when we return from cond_wait
|
||||
|
||||
}
|
||||
|
||||
// decrement the semaphore value
|
||||
mSemaphoreValue = 0;
|
||||
|
||||
// unlock the mutex again
|
||||
pthread_mutex_unlock( &( mutexPointer[0] ) );
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BinarySemaphore::signal() {
|
||||
|
||||
// get a pointer to the cond
|
||||
pthread_cond_t *condPointer =
|
||||
(pthread_cond_t *)mNativeObjectPointerA;
|
||||
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointerB;
|
||||
|
||||
|
||||
// lock the mutex
|
||||
pthread_mutex_lock( &( mutexPointer[0] ) );
|
||||
|
||||
// increment the semaphore value
|
||||
mSemaphoreValue = 1;
|
||||
|
||||
pthread_cond_signal( &( condPointer[0] ) );
|
||||
|
||||
|
||||
// unlock the mutex
|
||||
pthread_mutex_unlock( &( mutexPointer[0] ) );
|
||||
}
|
76
minorGems/system/linux/MutexLockLinux.cpp
Normal file
76
minorGems/system/linux/MutexLockLinux.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-October-18 Jason Rohrer
|
||||
* Moved common include out of header and into platform-specific cpp files,
|
||||
* since MemoryTrack uses a mutex lock.
|
||||
* Changed to use malloc instead of new internally to work with debugMemory.
|
||||
* Made use of mNativeObjectPointer a bit cleaner.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#include <minorGems/system/MutexLock.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Linux-specific implementation of the MutexLock class member functions.
|
||||
*
|
||||
* May also be compatible with other POSIX-like systems.
|
||||
*
|
||||
* To compile:
|
||||
* g++ -lpthread
|
||||
*/
|
||||
|
||||
|
||||
MutexLock::MutexLock() {
|
||||
// allocate a mutex structure on the heap
|
||||
mNativeObjectPointer = malloc( sizeof( pthread_mutex_t ) );
|
||||
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointer;
|
||||
|
||||
// init the mutex
|
||||
pthread_mutex_init( mutexPointer, NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
MutexLock::~MutexLock() {
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointer;
|
||||
|
||||
// destroy the mutex
|
||||
pthread_mutex_destroy( mutexPointer );
|
||||
|
||||
// de-allocate the mutex structure from the heap
|
||||
free( mNativeObjectPointer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MutexLock::lock() {
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointer;
|
||||
|
||||
pthread_mutex_lock( mutexPointer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MutexLock::unlock() {
|
||||
// get a pointer to the mutex
|
||||
pthread_mutex_t *mutexPointer =
|
||||
(pthread_mutex_t *)mNativeObjectPointer;
|
||||
|
||||
pthread_mutex_unlock( mutexPointer );
|
||||
}
|
247
minorGems/system/linux/ThreadLinux.cpp
Normal file
247
minorGems/system/linux/ThreadLinux.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2000-December-13 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Added missing sleep() implementation.
|
||||
*
|
||||
* 2002-March-27 Jason Rohrer
|
||||
* Added support for gprof-friendly thread wrappers.
|
||||
* Fixed a compile bug when gprof threads disabled.
|
||||
*
|
||||
* 2002-August-5 Jason Rohrer
|
||||
* Removed an unused variable.
|
||||
*
|
||||
* 2003-February-3 Jason Rohrer
|
||||
* Fixed sleep to be thread safe (signals were interrupting thread sleeps).
|
||||
*
|
||||
* 2004-March-31 Jason Rohrer
|
||||
* Added support for detatched mode.
|
||||
*
|
||||
* 2005-January-22 Jason Rohrer
|
||||
* Added a static sleep function.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <minorGems/system/Thread.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Linux-specific implementation of the Thread class member functions.
|
||||
*
|
||||
* May also be compatible with other POSIX-like systems.
|
||||
*
|
||||
* To compile:
|
||||
* g++ -lpthread
|
||||
* If thread profiling is desired for gprof on linux, compile
|
||||
* with -DUSE_GPROF_THREADS (otherwise, only main thread is profiled).
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef USE_GPROF_THREADS
|
||||
// prototype
|
||||
int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr,
|
||||
void * (*start_routine)(void *), void * arg );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// prototype
|
||||
/**
|
||||
* A wrapper for the run method, since pthreads won't take
|
||||
* a class's member function. Takes a pointer to the Thread to run,
|
||||
* cast as a void*;
|
||||
*/
|
||||
void *linuxThreadFunction( void * );
|
||||
|
||||
|
||||
|
||||
Thread::Thread() {
|
||||
// allocate a pthread structure on the heap
|
||||
mNativeObjectPointer = (void *)( new pthread_t[1] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Thread::~Thread() {
|
||||
// de-allocate the pthread structure from the heap
|
||||
pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer;
|
||||
delete [] threadPointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Thread::start( char inDetach ) {
|
||||
|
||||
mIsDetached = inDetach;
|
||||
|
||||
// get a pointer to the pthread
|
||||
pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer;
|
||||
|
||||
// create the pthread, which also sets it running
|
||||
#ifdef USE_GPROF_THREADS
|
||||
gprof_pthread_create( &( threadPointer[0] ), NULL,
|
||||
linuxThreadFunction, (void*)this );
|
||||
#else
|
||||
pthread_create( &( threadPointer[0] ), NULL,
|
||||
linuxThreadFunction, (void*)this );
|
||||
#endif
|
||||
|
||||
if( mIsDetached ) {
|
||||
pthread_detach( threadPointer[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Thread::join() {
|
||||
void *joinStat;
|
||||
|
||||
pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer;
|
||||
|
||||
pthread_join( threadPointer[0], &joinStat );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Thread::staticSleep( unsigned long inTimeInMilliseconds ) {
|
||||
|
||||
unsigned long seconds = inTimeInMilliseconds / 1000;
|
||||
unsigned long milliseconds = inTimeInMilliseconds % 1000;
|
||||
|
||||
struct timespec remainingSleepTimeStruct;
|
||||
remainingSleepTimeStruct.tv_sec = seconds;
|
||||
remainingSleepTimeStruct.tv_nsec = milliseconds * 1000000;
|
||||
|
||||
struct timespec timeToSleepStruct;
|
||||
|
||||
// sleep repeatedly, ignoring signals, untill we use up all of the time
|
||||
int sleepReturn = -1;
|
||||
while( sleepReturn == -1 ) {
|
||||
|
||||
timeToSleepStruct.tv_sec = remainingSleepTimeStruct.tv_sec;
|
||||
timeToSleepStruct.tv_nsec = remainingSleepTimeStruct.tv_nsec;
|
||||
|
||||
sleepReturn =
|
||||
nanosleep( &timeToSleepStruct, &remainingSleepTimeStruct );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// takes a pointer to a Thread object as the data value
|
||||
void *linuxThreadFunction( void *inPtrToThread ) {
|
||||
Thread *threadToRun = (Thread *)inPtrToThread;
|
||||
threadToRun->run();
|
||||
|
||||
if( threadToRun->isDetatched() ) {
|
||||
// thread detached, so we must destroy it
|
||||
delete threadToRun;
|
||||
}
|
||||
|
||||
return inPtrToThread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_GPROF_THREADS
|
||||
|
||||
|
||||
|
||||
// found at http://sam.zoy.org/doc/programming/gprof.html
|
||||
#include <sys/time.h>
|
||||
/*
|
||||
* pthread_create wrapper for gprof compatibility
|
||||
*
|
||||
* needed headers: <pthread.h>
|
||||
* <sys/time.h>
|
||||
*/
|
||||
typedef struct wrapper_s {
|
||||
void * (*start_routine)(void *);
|
||||
void * arg;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t wait;
|
||||
struct itimerval itimer;
|
||||
} wrapper_t;
|
||||
|
||||
|
||||
|
||||
static void * wrapper_routine(void *);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Same prototype as pthread_create; use some #define magic to
|
||||
* transparently replace it in other files
|
||||
*/
|
||||
int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr,
|
||||
void * (*start_routine)(void *), void * arg ) {
|
||||
|
||||
wrapper_t wrapper_data;
|
||||
int i_return;
|
||||
|
||||
/* Initialize the wrapper structure */
|
||||
wrapper_data.start_routine = start_routine;
|
||||
wrapper_data.arg = arg;
|
||||
getitimer(ITIMER_PROF, &wrapper_data.itimer);
|
||||
pthread_cond_init(&wrapper_data.wait, NULL);
|
||||
pthread_mutex_init(&wrapper_data.lock, NULL);
|
||||
pthread_mutex_lock(&wrapper_data.lock);
|
||||
|
||||
/* The real pthread_create call */
|
||||
i_return = pthread_create(thread, attr, &wrapper_routine,
|
||||
&wrapper_data);
|
||||
|
||||
/* If the thread was successfully spawned, wait for the data
|
||||
* to be released */
|
||||
if( i_return == 0 ) {
|
||||
pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&wrapper_data.lock);
|
||||
pthread_mutex_destroy(&wrapper_data.lock);
|
||||
pthread_cond_destroy(&wrapper_data.wait);
|
||||
return i_return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The wrapper function in charge for setting the itimer value
|
||||
*/
|
||||
static void * wrapper_routine( void * data ) {
|
||||
|
||||
/* Put user data in thread-local variables */
|
||||
void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine;
|
||||
void * arg = ((wrapper_t*)data)->arg;
|
||||
|
||||
/* Set the profile timer value */
|
||||
setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);
|
||||
|
||||
/* Tell the calling thread that we don't need its data anymore */
|
||||
pthread_mutex_lock(&((wrapper_t*)data)->lock);
|
||||
pthread_cond_signal(&((wrapper_t*)data)->wait);
|
||||
pthread_mutex_unlock(&((wrapper_t*)data)->lock);
|
||||
|
||||
/* Call the real function */
|
||||
return start_routine(arg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
115
minorGems/system/semaphoreTest.cpp
Normal file
115
minorGems/system/semaphoreTest.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Made printing in threads thread-safe.
|
||||
*/
|
||||
|
||||
#include "BinarySemaphore.h"
|
||||
#include "Semaphore.h"
|
||||
#include "Thread.h"
|
||||
#include "ThreadSafePrinter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* Thread that waits on a semaphore.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class WaitingThread : public Thread {
|
||||
|
||||
public:
|
||||
|
||||
WaitingThread( int inID, Semaphore *inSemaphore );
|
||||
|
||||
// override the run method from PThread
|
||||
void run();
|
||||
|
||||
private:
|
||||
Semaphore *mSemaphore;
|
||||
int mID;
|
||||
};
|
||||
|
||||
|
||||
inline WaitingThread::WaitingThread( int inID, Semaphore *inSemaphore )
|
||||
: mID( inID ), mSemaphore( inSemaphore ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void WaitingThread::run() {
|
||||
for( int i=0; i<10; i++ ) {
|
||||
ThreadSafePrinter::printf( "%d waiting for signal %d...\n", mID, i );
|
||||
mSemaphore->wait();
|
||||
ThreadSafePrinter::printf( "%d received signal %d.\n", mID, i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread that signals on a semaphore.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class SignalingThread : public Thread {
|
||||
|
||||
public:
|
||||
|
||||
SignalingThread( Semaphore *inSemaphore );
|
||||
|
||||
// override the run method from PThread
|
||||
void run();
|
||||
|
||||
private:
|
||||
Semaphore *mSemaphore;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline SignalingThread::SignalingThread( Semaphore *inSemaphore )
|
||||
: mSemaphore( inSemaphore ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void SignalingThread::run() {
|
||||
for( int i=0; i<5; i++ ) {
|
||||
sleep( 5000 );
|
||||
ThreadSafePrinter::printf( "Signaling 20 times\n" );
|
||||
for( int j=0; j<20; j++ ) {
|
||||
mSemaphore->signal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
Semaphore *semph = new Semaphore();
|
||||
|
||||
SignalingThread *threadS = new SignalingThread( semph );
|
||||
|
||||
WaitingThread **threadW = new WaitingThread*[10];
|
||||
for( i=0; i<10; i++ ) {
|
||||
threadW[i] = new WaitingThread( i, semph );
|
||||
threadW[i]->start();
|
||||
}
|
||||
|
||||
threadS->start();
|
||||
|
||||
for( i=0; i<10; i++ ) {
|
||||
threadW[i]->join();
|
||||
delete threadW[i];
|
||||
}
|
||||
threadS->join();
|
||||
|
||||
delete semph;
|
||||
delete threadS;
|
||||
delete [] threadW;
|
||||
return 0;
|
||||
}
|
33
minorGems/system/unix/LauncherUnix.cpp
Normal file
33
minorGems/system/unix/LauncherUnix.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-10 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/Launcher.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
void Launcher::launchCommand( char *inCommandName,
|
||||
char **inArguments ) {
|
||||
|
||||
|
||||
int forkValue = fork();
|
||||
|
||||
if( forkValue == 0 ) {
|
||||
// we're in child process, so exec command
|
||||
|
||||
execvp( inCommandName, inArguments );
|
||||
|
||||
// we'll never return from this call
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
40
minorGems/system/unix/TimeUnix.cpp
Normal file
40
minorGems/system/unix/TimeUnix.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-October-29 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-March-13 Jason Rohrer
|
||||
* Added include of time.h so that FreeBSD compile will work.
|
||||
* Changed to use newer gettimeofday that should work on all unix platforms.
|
||||
* Fixed a conversion bug.
|
||||
*/
|
||||
|
||||
|
||||
#include "minorGems/system/Time.h"
|
||||
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
void Time::getCurrentTime( unsigned long *outSeconds,
|
||||
unsigned long *outMilliseconds ) {
|
||||
|
||||
struct timeval currentTime;
|
||||
|
||||
gettimeofday( ¤tTime, NULL );
|
||||
|
||||
|
||||
*outMilliseconds = currentTime.tv_usec / 1000;
|
||||
*outSeconds = currentTime.tv_sec;
|
||||
|
||||
}
|
||||
|
||||
|
94
minorGems/system/win32/BinarySemaphoreWin32.cpp
Normal file
94
minorGems/system/win32/BinarySemaphoreWin32.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-March-4 Jason Rohrer
|
||||
* Replaced include of <winbase.h> and <windef.h> with <windows.h>
|
||||
* to fix compile bugs encountered with newer windows compilers.
|
||||
*
|
||||
* 2003-August-26 Jason Rohrer
|
||||
* Added support for timeouts on wait.
|
||||
*/
|
||||
|
||||
#include "minorGems/system/BinarySemaphore.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
/**
|
||||
* Win32-specific implementation of the BinarySemaphore class member functions.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Native object pointer A is the semaphore handle.
|
||||
* Pointer B is not used.
|
||||
*/
|
||||
|
||||
|
||||
BinarySemaphore::BinarySemaphore() :
|
||||
mSemaphoreValue( 0 ) {
|
||||
|
||||
// allocate a handle on the heap
|
||||
mNativeObjectPointerA = (void *)( new HANDLE[1] );
|
||||
|
||||
// retrieve handle from the heap
|
||||
HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA;
|
||||
|
||||
|
||||
semaphorePointer[0] = CreateSemaphore(
|
||||
(LPSECURITY_ATTRIBUTES) NULL, // no attributes
|
||||
0, // initial count
|
||||
1, // maximum count
|
||||
(LPCTSTR) NULL ); // no name
|
||||
|
||||
}
|
||||
|
||||
BinarySemaphore::~BinarySemaphore() {
|
||||
|
||||
// retrieve handle from the heap
|
||||
HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA;
|
||||
|
||||
// destroy the semaphore
|
||||
CloseHandle( semaphorePointer[0] );
|
||||
|
||||
// de-allocate the handle from the heap
|
||||
delete [] semaphorePointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int BinarySemaphore::wait( int inTimeoutInMilliseconds ) {
|
||||
|
||||
// retrieve handle from the heap
|
||||
HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA;
|
||||
|
||||
if( inTimeoutInMilliseconds == -1 ) {
|
||||
WaitForSingleObject( semaphorePointer[0], INFINITE );
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
// timeout
|
||||
int result = WaitForSingleObject( semaphorePointer[0],
|
||||
inTimeoutInMilliseconds );
|
||||
|
||||
if( result == WAIT_TIMEOUT ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BinarySemaphore::signal() {
|
||||
|
||||
// retrieve handle from the heap
|
||||
HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA;
|
||||
|
||||
ReleaseSemaphore( semaphorePointer[0], 1, (LPLONG) NULL );
|
||||
}
|
29
minorGems/system/win32/LauncherWin32.cpp
Normal file
29
minorGems/system/win32/LauncherWin32.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-10 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2003-March-24 Jason Rohrer
|
||||
* Fixed a syntax typo.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/Launcher.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
|
||||
|
||||
void Launcher::launchCommand( char *inCommandName,
|
||||
char **inArguments ) {
|
||||
|
||||
_spawnvp( _P_NOWAIT,
|
||||
inCommandName,
|
||||
inArguments );
|
||||
}
|
||||
|
||||
|
||||
|
81
minorGems/system/win32/MutexLockWin32.cpp
Normal file
81
minorGems/system/win32/MutexLockWin32.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-March-4 Jason Rohrer
|
||||
* Replaced include of <winbase.h> and <windef.h> with <windows.h>
|
||||
* to fix compile bugs encountered with newer windows compilers.
|
||||
*
|
||||
* 2002-October-18 Jason Rohrer
|
||||
* Moved common include out of header and into platform-specific cpp files,
|
||||
* since MemoryTrack uses a mutex lock.
|
||||
*
|
||||
* 2002-October-19 Jason Rohrer
|
||||
* Changed to use malloc instead of new internally to work with debugMemory.
|
||||
* Made use of mNativeObjectPointer a bit cleaner.
|
||||
* Fixed a few bugs with new use of mNativeObjectPointer.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#include "minorGems/system/MutexLock.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Win32-specific implementation of the MutexLock class member functions.
|
||||
*/
|
||||
|
||||
|
||||
MutexLock::MutexLock() {
|
||||
// allocate a handle on the heap
|
||||
mNativeObjectPointer = malloc( sizeof( HANDLE ) );
|
||||
|
||||
// retrieve handle from the heap
|
||||
HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
// create the mutex
|
||||
*mutexPointer = CreateMutex(
|
||||
(LPSECURITY_ATTRIBUTES) NULL, // no attributes
|
||||
(BOOL) false, // not initially locked
|
||||
(LPCTSTR) NULL ); // no name
|
||||
}
|
||||
|
||||
|
||||
|
||||
MutexLock::~MutexLock() {
|
||||
// retrieve handle from the heap
|
||||
HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
// destroy the mutex
|
||||
CloseHandle( *mutexPointer );
|
||||
|
||||
// de-allocate the mutex structure from the heap
|
||||
free( mutexPointer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MutexLock::lock() {
|
||||
// retrieve handle from the heap
|
||||
HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
WaitForSingleObject( *mutexPointer, INFINITE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MutexLock::unlock() {
|
||||
// retrieve handle from the heap
|
||||
HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
ReleaseMutex( *mutexPointer );
|
||||
}
|
||||
|
108
minorGems/system/win32/ThreadWin32.cpp
Normal file
108
minorGems/system/win32/ThreadWin32.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-January-27 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-March-4 Jason Rohrer
|
||||
* Replaced include of <winbase.h> and <windef.h> with <windows.h>
|
||||
* to fix compile bugs encountered with newer windows compilers.
|
||||
*
|
||||
* 2004-March-31 Jason Rohrer
|
||||
* Added missing call to CloseHandle in destructor.
|
||||
* Added support for detatched mode.
|
||||
*
|
||||
* 2004-April-1 Jason Rohrer
|
||||
* Fixed a bug in CloseHandle call pointed out by Mycroftxxx.
|
||||
*
|
||||
* 2005-January-22 Jason Rohrer
|
||||
* Added a static sleep function.
|
||||
*/
|
||||
|
||||
#include "minorGems/system/Thread.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
/**
|
||||
* Win32-specific implementation of the Thread class member functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// prototype
|
||||
/**
|
||||
* A wrapper for the run method, since windows thread (perhaps) won't take
|
||||
* a class's member function. Takes a pointer to the Thread to run,
|
||||
* cast as a void*;
|
||||
*/
|
||||
DWORD WINAPI win32ThreadFunction( void * );
|
||||
|
||||
|
||||
|
||||
Thread::Thread() {
|
||||
// allocate a handle on the heap
|
||||
mNativeObjectPointer = (void *)( new HANDLE[1] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Thread::~Thread() {
|
||||
// get a pointer to the allocated handle
|
||||
HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
// close the handle to ensure that the thread resources are freed
|
||||
CloseHandle( threadPointer[0] );
|
||||
|
||||
// de-allocate the thread handle from the heap
|
||||
delete [] threadPointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Thread::start( char inDetach ) {
|
||||
|
||||
mIsDetached = inDetach;
|
||||
|
||||
// get a pointer to the allocated handle
|
||||
HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
DWORD threadID;
|
||||
|
||||
threadPointer[0] = CreateThread(
|
||||
(LPSECURITY_ATTRIBUTES)NULL, // no attributes
|
||||
(DWORD)0, // default stack size
|
||||
win32ThreadFunction, // function
|
||||
(LPVOID)this, // function arg
|
||||
(DWORD)0, // no creation flags (start thread immediately)
|
||||
&threadID );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Thread::join() {
|
||||
|
||||
HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer;
|
||||
|
||||
WaitForSingleObject( threadPointer[0], INFINITE );
|
||||
}
|
||||
|
||||
|
||||
void Thread::staticSleep( unsigned long inTimeInMilliseconds ) {
|
||||
Sleep( inTimeInMilliseconds );
|
||||
}
|
||||
|
||||
|
||||
// takes a pointer to a Thread object as the data value
|
||||
DWORD WINAPI win32ThreadFunction( void *inPtrToThread ) {
|
||||
Thread *threadToRun = (Thread *)inPtrToThread;
|
||||
threadToRun->run();
|
||||
|
||||
|
||||
if( threadToRun->isDetatched() ) {
|
||||
// thread detached, so we must destroy it
|
||||
delete threadToRun;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
77
minorGems/system/win32/TimeWin32.cpp
Normal file
77
minorGems/system/win32/TimeWin32.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-November-7 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2002-April-11 Jason Rohrer
|
||||
* Added missing include, and fixed a bug.
|
||||
*
|
||||
* 2004-January-29 Jason Rohrer
|
||||
* Fixed so that 0-point of time is the same as on other platforms.
|
||||
*
|
||||
* 2004-October-14 Jason Rohrer
|
||||
* Fixed bug in second/millisecond callibration.
|
||||
* Fixed bug in win32 time to ANSI time translation.
|
||||
* Fixed daylight savings time bug.
|
||||
*/
|
||||
|
||||
|
||||
#include "minorGems/system/Time.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Windows implementation of Time.h.
|
||||
*
|
||||
* The 0-point should match the ANSI standard.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void Time::getCurrentTime( unsigned long *outSeconds,
|
||||
unsigned long *outMilliseconds ) {
|
||||
// convert from win32 broken-down time (which has msec resolution)
|
||||
// to an ANSI time struct and then convert to an absolute time in
|
||||
// seconds
|
||||
// This procedure ensures that the 0-point matches the ANSI standard.
|
||||
|
||||
// note:
|
||||
// we cannot simply call ANSI time() to get the seconds and then rely
|
||||
// on GetLocalTime to get the milliseconds, since the seconds value
|
||||
// used by GetLocalTime is (strangely enough) not calibrated to the seconds
|
||||
// value of time().
|
||||
// In other words, it is possible for the time() seconds to advance
|
||||
// at a different clock cycle than the GetLocalTime seconds.
|
||||
|
||||
// get time using a win32 call
|
||||
SYSTEMTIME win32TimeStruct;
|
||||
GetLocalTime( &win32TimeStruct );
|
||||
|
||||
// convert this win32 structure to the ANSI standard structure
|
||||
struct tm ansiTimeStruct;
|
||||
|
||||
ansiTimeStruct.tm_sec = win32TimeStruct.wSecond;
|
||||
ansiTimeStruct.tm_min = win32TimeStruct.wMinute;
|
||||
ansiTimeStruct.tm_hour = win32TimeStruct.wHour;
|
||||
ansiTimeStruct.tm_mday = win32TimeStruct.wDay;
|
||||
// ANSI time struct has month in range [0..11]
|
||||
ansiTimeStruct.tm_mon = win32TimeStruct.wMonth - 1;
|
||||
// ANSI time struct has year that is an offset from 1900
|
||||
ansiTimeStruct.tm_year = win32TimeStruct.wYear - 1900;
|
||||
// unknown daylight savings time (dst) status
|
||||
// if we fail to init this value, we can get inconsistent results
|
||||
ansiTimeStruct.tm_isdst = -1;
|
||||
|
||||
unsigned long secondsSinceEpoch = mktime( &ansiTimeStruct );
|
||||
|
||||
*outSeconds = secondsSinceEpoch;
|
||||
*outMilliseconds = (unsigned long)( win32TimeStruct.wMilliseconds );
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue