00001 #ifndef MY_SEMAPHORE_
00002 #define MY_SEMAPHORE_
00003
00010 extern "C"
00011 {
00012 #include <sys/fcntl.h>
00013 #include <sys/errno.h>
00014 #include <limits.h>
00015 }
00016
00017
00018 #ifdef CYGWIN_COMPAT
00019 extern "C"
00020 {
00021
00022 #include "/usr/include/semaphore.h"
00023 }
00024 #else
00025 extern "C"
00026 {
00027 #include <semaphore.h>
00028 }
00029 #endif
00030
00031
00033 class CSemaphore_exception : public std::exception
00034 {
00035 private:
00036 const std::string Message;
00037
00038 public:
00039 explicit CSemaphore_exception(const std::string& Msg) throw()
00040 : Message(Msg)
00041 {
00042 #if defined(VERBOSE) || defined(DEBUG)
00043 cerr << "throwing exception: " << Msg << endl;
00044 #endif
00045 }
00046
00047 virtual ~CSemaphore_exception() throw() { }
00048
00049 virtual const char* what() const throw()
00050 {
00051 return Message.c_str();
00052 }
00053 };
00054
00055
00057 class CSemaphore : private ForbidAssignment
00058 {
00059 private:
00060 sem_t resource_counter;
00061 public:
00062 CSemaphore(const unsigned int my_resource_counter)
00063 {
00064 if (my_resource_counter>static_cast<unsigned long int>(SEM_VALUE_MAX))
00065 throw CSemaphore_exception("CSemaphore::constructor: my_resource_counter>SEM_VALUE_MAX");
00066 if (sem_init(&resource_counter, 0, my_resource_counter))
00067 throw CSemaphore_exception("CSemaphore::constructor: initialization failed!");
00068 }
00069 ~CSemaphore()
00070 {
00071 if (sem_destroy(&resource_counter))
00072 throw CSemaphore_exception("CSemaphore::destructor: failed!");
00073 }
00074 void post()
00075 {
00076 if (sem_post(&resource_counter)) throw CSemaphore_exception("CSemaphore_post");
00077 }
00078 void wait()
00079 {
00080 if (sem_wait(&resource_counter)) throw CSemaphore_exception("CSemaphore_wait");
00081 }
00082 bool trywait()
00083 {
00084 int retval=(sem_trywait(&resource_counter));
00085 if (retval==-1 && errno!=EAGAIN) throw CSemaphore_exception("CSemaphore_trywait");
00086 return (retval==0);
00087 }
00088 int getvalue()
00089 {
00090 int retval;
00091 if (sem_getvalue(&resource_counter,&retval)) throw CSemaphore_exception("CSemaphore_getvalue");
00092 return retval;
00093 }
00094 };
00095
00096
00098 class CNamedSemaphore : private ForbidAssignment
00099 {
00100 private:
00101 sem_t *p_resource_counter;
00102 public:
00103 CNamedSemaphore(const char *const name, const unsigned int my_resource_counter)
00104 {
00105 if (my_resource_counter>static_cast<unsigned long int>(SEM_VALUE_MAX))
00106 throw CSemaphore_exception("CNamedSemaphore::constructor: my_resource_counter>SEM_VALUE_MAX");
00107 p_resource_counter = sem_open(name, O_CREAT, S_IRWXU|S_IRWXG, my_resource_counter);
00108 if (p_resource_counter == SEM_FAILED)
00109 throw CSemaphore_exception("CNamedSemaphore::constructor: initialization failed!");
00110 }
00111 ~CNamedSemaphore()
00112 {
00113 if (sem_close(p_resource_counter))
00114 throw CSemaphore_exception("CNamedSemaphore::destructor: failed!");
00115 }
00116 void post()
00117 {
00118 if (sem_post(p_resource_counter)) throw CSemaphore_exception("CNamedSemaphore_post");
00119 }
00120 void wait()
00121 {
00122 if (sem_wait(p_resource_counter)) throw CSemaphore_exception("CNamedSemaphore_wait");
00123 }
00124 bool trywait()
00125 {
00126 int retval=(sem_trywait(p_resource_counter));
00127 if (retval==-1 && errno!=EAGAIN) throw CSemaphore_exception("CNamedSemaphore_trywait");
00128 return (retval==0);
00129 }
00130 int getvalue()
00131 {
00132 int retval;
00133 if (sem_getvalue(p_resource_counter,&retval)) throw CSemaphore_exception("CNamedSemaphore_getvalue");
00134 return retval;
00135 }
00136 };
00137
00138
00147 class CConditionalNamedSemaphorePostAtDestruction : private ForbidAssignment
00148 {
00149 private:
00150 CNamedSemaphore &Sem;
00151 bool condition;
00152 public:
00153 CConditionalNamedSemaphorePostAtDestruction(CNamedSemaphore &mySem, const bool initial_condition)
00154 : Sem(mySem), condition(initial_condition) { }
00155 ~CConditionalNamedSemaphorePostAtDestruction() { if (condition) Sem.post(); }
00156 void set_condition(const bool new_condition = true) { condition=new_condition; }
00157 };
00158
00159
00160 #endif