00001 #ifndef __SEMAPHORESET_H
00002 #define __SEMAPHOERSET_H
00003
00004 #include <string.h>
00005 #include <sys/types.h>
00006 #include <sys/ipc.h>
00007 #include <sys/sem.h>
00008 #include "ExceptionBase.h"
00009
00010 namespace SemSet
00011 {
00012 #define ALL_SEMS 0
00013
00014 typedef union semun
00015 {
00016 int val;
00017 struct smid_ds *buf;
00018 ushort *array;
00019 } arg;
00020
00021
00028 class SemException : public ExceptionBase
00029 {
00030 public:
00034 SemException() : ExceptionBase() {};
00035
00041 SemException(const char* mess) : ExceptionBase(mess) {};
00042
00046 ~SemException() {};
00047 };
00048
00049
00056 class SemUnknownSetException : public ExceptionBase
00057 {
00058 public:
00062 SemUnknownSetException() : ExceptionBase() {};
00063
00069 SemUnknownSetException(const char* mess) : ExceptionBase(mess) {};
00070
00074 ~SemUnknownSetException() {};
00075 };
00076
00077
00084 class SemaphoreSet
00085 {
00086 public:
00090 enum SemSetRetVal { OK, FAIL };
00091
00097 SemaphoreSet(int numOfSems)
00098 {
00099 semSetId = semget(IPC_PRIVATE, numOfSems, IPC_CREAT | 0666);
00100 if (semSetId == -1)
00101 {
00102 semSetId = FAIL;
00103 return;
00104 }
00105
00106 arg semVal;
00107 semVal.val = 1;
00108
00109 for (int i = 0; i < numOfSems; i++)
00110 {
00111 int tmpRet = semctl(semSetId, i, SETVAL, semVal);
00112 if (tmpRet == -1)
00113 {
00114 semSetId = FAIL;
00115 destroyAll();
00116 return;
00117 }
00118 }
00119 }
00120
00126 SemaphoreSet(const SemaphoreSet &otherSet)
00127 {
00128 semSetId = otherSet.semSetId;
00129 }
00130
00134 ~SemaphoreSet() throw(SemUnknownSetException)
00135 {
00136 if (semSetId > 0)
00137 {
00138 try
00139 {
00140 destroyAll();
00141 }
00142 catch (SemException &e)
00143 {
00144 throw SemUnknownSetException("SemaphoreSet::~SemaphoreSet : set was probably already destroyed by another process");
00145 }
00146 }
00147 }
00148
00156 SemSetRetVal lock(int semNum) throw(SemException)
00157 {
00158 struct sembuf op;
00159
00160 if (semSetId <= 0)
00161 throw SemException("Semaphore set in wrong condition");
00162
00163 op.sem_num = semNum;
00164 op.sem_op = -1;
00165 op.sem_flg = SEM_UNDO;
00166
00167 int tmpRet = semop(semSetId, &op, 1);
00168 if (tmpRet == -1)
00169 return FAIL;
00170
00171 return OK;
00172 }
00173
00181 SemSetRetVal unlock(int semNum) throw(SemException)
00182 {
00183 struct sembuf op;
00184
00185 if (semSetId <= 0)
00186 throw SemException("Semaphore set in wrong condition");
00187
00188 op.sem_num = semNum;
00189 op.sem_op = 1;
00190 op.sem_flg = SEM_UNDO;
00191
00192 int tmpRet = semop(semSetId, &op, 1);
00193 if (tmpRet == -1)
00194 return FAIL;
00195
00196 return OK;
00197 }
00198
00199 private:
00200 int semSetId;
00201
00202 SemSetRetVal destroyAll()
00203 {
00204 arg semVal;
00205
00206 if (semSetId <= 0)
00207 throw SemException("Semaphore set in wrong condition");
00208
00209 int tmpRet = semctl(semSetId, ALL_SEMS, IPC_RMID, semVal);
00210 if (tmpRet == -1)
00211 {
00212 semSetId = FAIL;
00213 throw SemException("Couldn't destroy a semaphore set");
00214 }
00215 return OK;
00216 }
00217 };
00218 }
00219
00220 #endif //__SEMAPHOERESET_H