/* * This Software is the original work of Daniel TUNG * This Software is submitted in partial fulfillment of the * requirements for the degree of BCSE. * Dept. Computer Science, Monash University 2000 * * Copyright (c) 2000 beetung@cs.monash.edu.au * beetung@geocities.com */ #ifndef SEMAPHORE_H #define SEMAPHORE_H #include extern "C" { #include #include // what is this for? }; //// //// My implementation of a Semaphore class //// ///////////////////////////////// class MySemaphore { ///////////////////////////////// //// //// Note: The ~dtor() would destroy our semaphore when its called, //// ie, when out of scope! Hence, use this class with extra care //// especially in a Consumer and Producer topology. Class MySemaphore's //// destructor should _NEVER_ be called before the destruction of class //// Consumer and Producer are complete. //// public: bool quit; char data; int idata; private: sem_t sem; public: //------------------ operator sem_t* (void) { return &sem; }; //------------------ /// Initialize a pthread style semaphore structure /// //------------------ MySemaphore(): quit (false) { //------------------ const int NON_SHARED_ACROSS_PROCESS =0; // dont wana share const int SEMA_INIT_VALUE = 0; // init as zero //// //// init the semaphore //// sem_init(&sem, NON_SHARED_ACROSS_PROCESS, SEMA_INIT_VALUE ); } /// destroy the semaphore //------------------ ~MySemaphore() { //------------------ cout << "~MySemaphore "<< sem_destroy(&sem) << endl; } /// Decrements our Semaphore by 1, or , block here. /// My implementation on Semaphore Wait - just a C++ wrapper /// //--------------------- inline void SemWait() { //--------------------- if ( !quit ) while ( sem_wait(&sem) !=0 ) {;} } /// Increments our Semaphore by 1 /// //--------------------- inline void SemPost() { //--------------------- sem_post(&sem); } /// /// Spin Test the semaphore value. /// /// WARNING : Dont use this function unless you are absolutely sure /// what you are doing!!! use SemPost() and SemWait() pair only!!!! //--------------------- inline int GetValue(void) { //--------------------- int semVal; return sem_getvalue(&sem,&semVal); } }; //// //// Common baseClass for Consumer and Producer, using //// encapsulation on Sema instead of inheritance. //// ///////////////////////////////// class BaseSema { ///////////////////////////////// private: int itmp; // temp int for sem_getvalue() on Car.h protected: MySemaphore& aSemaphore; bool& quit; char& data; int& idata; public: //------------------ BaseSema(MySemaphore &a) : aSemaphore(a),quit(a.quit), data(a.data),idata(a.idata) {;} BaseSema(BaseSema &a) : aSemaphore(a.aSemaphore),quit(a.aSemaphore.quit), data(a.aSemaphore.data),idata(a.aSemaphore.idata) {;} //------------------ //------------------ virtual ~BaseSema() { // needs virtual ~dtor() cos "delete on base*" can happen //------------------ cout << "~BaseSema() " << endl; // send out a final Post() so that all sleeping // processes can wake up // SemPost(); } //------------------ virtual void Consume() { run(); } virtual void Produce() { run(); } virtual void* run() = 0; //------------------ inline void setCommand (int myVal) { data =(char)myVal; } inline void setCommand (char myChar) { data = myChar; } inline char& getCommand (void) { return data; } inline int& CommandCount (void) { return idata; } //------------------ // send out a few final Post() so that all sleeping // processes can wake up before dying // //--------------------- inline void SemDie() { //--------------------- quit =true; SemPost(); } protected: /// /// Decrements our Semaphore by 1, or , block here. /// My implementation on Semaphore Wait - simple and direct /// //--------------------- inline void SemWait() { //--------------------- /// /// ignoring EINTR and -ve values, refer to Pthreads /// documentations.. /// if ( !quit ) while ( sem_wait(BaseSema::aSemaphore) !=0 ) {;} } /// /// Increments our Semaphore by 1 /// //--------------------- inline void SemPost() { //--------------------- // +1 on aSemaphore // sem_post(BaseSema::aSemaphore); } }; #ifdef CCC_SEMA_TEST #include "consumer.h" //------------------ int main() { //------------------ MySemaphore a; Consumer c(a); Producer p(a); c(); p(); } #endif // CCC_SEMA_TEST #endif // SEMAPHORE_H