00001
00009 #ifndef ATOMS_SEMAPHORE_HH
00010 #define ATOMS_SEMAPHORE_HH
00011
00012 #ifdef WORKING_SEM_T
00013 #include <semaphore.h>
00014 #endif
00015 #include <atoms/gen.hh>
00016 #ifndef WORKING_SEM_T
00017 #include <atoms/mutex.hh>
00018 #include <atoms/condition.hh>
00019 #endif
00020
00021 namespace atoms {
00022
00027 class Semaphore {
00028 public:
00029 Semaphore(unsigned n);
00030 ~Semaphore();
00031
00032 class Mon : public Monitor {
00033 public:
00034 Mon(Semaphore &s, bool l = true) : s(s), locked(false) {
00035 if (l) lock();
00036 }
00037
00038 ~Mon() { if (locked) unlock(); }
00039
00040 void lock() {
00041 assert(!locked);
00042 #ifdef WORKING_SEM_T
00043 int retval;
00044 while ((retval = sem_wait(&s)) == -1 && errno == EINTR) ;
00045 assert(retval == 0);
00046 #else
00047 Mutex::Mon mm(m);
00048 assert(count <= n);
00049 while (count == n)
00050 c.wait(mm);
00051 #endif
00052 locked = true;
00053 }
00054
00055 void unlock() {
00056 assert(locked);
00057 #ifdef WORKING_SEM_T
00058 int retval = sem_post(&s);
00059 #else
00060 Mutex::Mon mm(m);
00061 assert(count >= 1);
00062 if (count-- == n)
00063 c.signal();
00064 #endif
00065 assert(retval == 0);
00066 }
00067
00068 private:
00069 Semaphore &s;
00070 bool locked;
00071 };
00072
00073 private:
00074 #ifdef WORKING_SEM_T
00075 sem_t sem;
00076 #else
00077 unsigned n, count;
00078 Mutex m;
00079 Condition c;
00080 #endif
00081 };
00082
00083 }
00084 #endif // !ATOMS_SEMAPHORE_HH