00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <spl/io/Directory.h>
00024 #include <spl/threading/Semaphore.h>
00025 #include <spl/io/WinPerm.h>
00026
00027 #ifdef HAVE_SEMAPHORE_H
00028 #include <semaphore.h>
00029 #endif
00030
00031 #ifdef WIN32
00032 extern bool EncodePermissions(const Permissions& perm, _WinPerms &wperm);
00033 #else
00034 extern void EncodePermissions(const Permissions& perm, mode_t& mode);
00035 #endif
00036
00037 #ifndef WIN32
00038 static bool VerifyIPCName(const String& name)
00039 {
00040 return((name.Length() <= 14) && (name.IndexOf(Directory::SeperatorChar(), 0) < 0));
00041 }
00042 #endif
00043
00044 Semaphore::Semaphore
00045 (
00046 const String &name,
00047 uint32 value ,
00048 const Permissions& perm
00049
00050 )
00051 {
00052 if (value < 1)
00053 {
00054 throw new InvalidArgumentException("Invalid value");
00055 }
00056
00057 #ifdef WIN32
00058
00059 _name = name;
00060
00061 SECURITY_ATTRIBUTES sa;
00062 _WinPerms wperm;
00063
00064 EncodePermissions(perm, wperm);
00065
00066 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
00067 sa.lpSecurityDescriptor = wperm.pdesc;
00068 sa.bInheritHandle = FALSE;
00069
00070 _sem = ::CreateSemaphore(&sa, 0, value, _name.GetChars());
00071 if(_sem == NULL)
00072 {
00073 throw new Exception("CreateSemaphore");
00074 }
00075
00076
00077 ::ReleaseSemaphore(_sem, value, NULL);
00078
00079 #else
00080
00081 if(! VerifyIPCName(name))
00082 {
00083 throw new InvalidArgumentException("Invalid IPC name");
00084 }
00085
00086 _name = name;
00087
00088 mode_t mode;
00089 EncodePermissions(perm, mode);
00090 _sem = ::sem_open(_name.GetChars(), (O_CREAT | O_RDWR), mode, value);
00091 if(_sem == reinterpret_cast<sem_t *>(SEM_FAILED))
00092 {
00093 throw new Exception("sem_open");
00094 }
00095
00096 #endif
00097 }
00098
00099 Semaphore::~Semaphore()
00100 {
00101 #ifdef WIN32
00102
00103 if(_sem != NULL)
00104 ::CloseHandle(_sem);
00105
00106 #else
00107
00108 if(_sem != reinterpret_cast<sem_t *>(SEM_FAILED))
00109 {
00110 sem_close(_sem);
00111 #ifndef __CYGWIN__
00112 sem_unlink(_name.GetChars());
00113 #endif
00114 }
00115
00116 #endif
00117 }
00118
00119 void Semaphore::Lock()
00120 {
00121 #ifdef WIN32
00122
00123 if(::WaitForSingleObjectEx(_sem, INFINITE, TRUE) != WAIT_OBJECT_0)
00124 {
00125 throw new StateException("Error locking semaphore");
00126 }
00127
00128 #else
00129
00130 if(::sem_wait(_sem) != 0)
00131 {
00132 throw new StateException("Error locking semaphore");
00133 }
00134
00135 #endif
00136 }
00137
00138 bool Semaphore::TryWait()
00139 {
00140 #ifdef WIN32
00141
00142 return(::WaitForSingleObjectEx(_sem, 0, TRUE) == WAIT_OBJECT_0);
00143
00144 #else
00145
00146 return(::sem_trywait(_sem) == 0);
00147
00148 #endif
00149 }
00150
00151 void Semaphore::Unlock()
00152 {
00153 #ifdef WIN32
00154
00155 if(::ReleaseSemaphore(_sem, 1, NULL) != TRUE)
00156 {
00157 throw new StateException("Error unlocking semaphore");
00158 }
00159
00160 #else
00161
00162 if(::sem_post(_sem) != 0)
00163 {
00164 throw new StateException("Error unlocking semaphore") ;
00165 }
00166
00167 #endif
00168 }
00169
00170 int Semaphore::GetValue() const
00171 {
00172 #ifdef WIN32
00173
00174 return(-1);
00175
00176 #else
00177
00178 int val = 0;
00179 int e = ::sem_getvalue(_sem, &val);
00180
00181 return((e == 0) ? val : -1);
00182
00183 #endif
00184 }
00185
00186 #if defined(DEBUG) || defined(_DEBUG)
00187 void Semaphore::CheckMem() const
00188 {
00189 }
00190
00191 void Semaphore::ValidateMem() const
00192 {
00193 }
00194 #endif
00195