Initial source commit
This commit is contained in:
commit
f1384c11ee
335 changed files with 52715 additions and 0 deletions
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
|
Loading…
Add table
Add a link
Reference in a new issue