• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Semaphore.cpp

00001 /* Ported to SPL, original attribution below. */
00002 /* ---------------------------------------------------------------------------
00003    commonc++ - A C++ Common Class Library
00004    Copyright (C) 2005-2009  Mark A Lindner
00005 
00006    This file was ported from commonc++.
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License as published by the Free Software Foundation; either
00011    version 2 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Library General Public License for more details.
00017 
00018    You should have received a copy of the GNU Library General Public
00019    License along with this library; if not, write to the Free
00020    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 /* = 1 */,
00048     const Permissions& perm
00049                      /* = Permissions::USER_READ_WRITE */
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         // make all instances immediately available
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); // not supported
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