Go to the documentation of this file.00001 
00009 
00010 
00011 
00012 
00013 #include "../../include/ecl/ipc/semaphore_pos.hpp"
00014 
00015 #ifdef ECL_HAS_POSIX_SEMAPHORES
00016 
00017 #include <errno.h>
00018 #include <sstream>
00019 #include <ecl/errors/handlers.hpp>
00020 #include <ecl/exceptions/standard_exception.hpp>
00021 #include <ecl/time_lite/functions.hpp>
00022 
00023 
00024 
00025 
00026 
00027 namespace ecl {
00028 
00029 
00030 
00031 
00032 
00033 using std::string;
00034 using std::ostringstream;
00035 
00036 
00037 
00038 
00039 
00040 Semaphore::Semaphore() throw(StandardException) {
00041         
00042         throw StandardException(LOC, RaiiError);
00043 }
00044 
00045 Semaphore::Semaphore(const std::string& string_id) ecl_assert_throw_decl(StandardException):
00046         name(string("/"+string_id)),
00047         semaphore(NULL)
00048 {
00049     
00050 
00051 
00052     
00053 
00054 
00055 
00056 
00057 
00058     static const int open_flags = O_CREAT;
00059     
00060 
00061 
00062     
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082     static const int permissions = S_IRWXU|S_IRWXG|S_IRWXO;
00083     
00084 
00085 
00086 
00087     static const int initial_value_unlocked = 1;
00088 
00089     
00090 
00091 
00092     semaphore = sem_open(name.c_str(),open_flags,permissions,initial_value_unlocked);
00093     ecl_assert_throw(semaphore != SEM_FAILED, ipc::openSemaphoreException(LOC));
00094 }
00095 
00096 Semaphore::~Semaphore()
00097 {
00098         
00099     sem_close(semaphore);
00100         
00101     sem_unlink(name.c_str());
00102 }
00103 
00104 void Semaphore::lock()
00105 {
00106         sem_wait(semaphore);
00107 }
00108 
00109 int Semaphore::count()
00110 {
00111         
00112     int semaphore_count;
00113     sem_getvalue(semaphore,&semaphore_count);
00114     return semaphore_count;
00115 }
00116 
00117 void Semaphore::unlock()
00118 {
00119         
00120         
00121     if ( count() == 1 ) { 
00122         return;
00123     } else {
00124         sem_post(semaphore);
00125     }
00126 }
00127 
00128 bool Semaphore::trylock()
00129 {
00130         
00131         if (  sem_trywait( semaphore ) == 0 ) {
00132                 return true;
00133         } else {
00134                 
00135                 
00136                 return false;
00137         }
00138 }
00139 
00140 bool Semaphore::trylock( const Duration &timeout ) ecl_debug_throw_decl(StandardException) {
00141 
00142     #if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L
00143                 long tnsec;
00144                 timespec ctime;
00145 
00146                 if ( epoch_time(ctime).flag() != NoError ) { return false; }
00147 
00148                 ctime.tv_sec += timeout.sec();
00149 
00150                 tnsec = ctime.tv_nsec + timeout.nsec();
00151                 if(tnsec >=  999999999 ) { ctime.tv_sec += 1; }
00152                 tnsec %= 1000000000;
00153                 ctime.tv_nsec = tnsec;
00154 
00155                 
00156                 
00157                 
00158                 int result = sem_timedwait( semaphore, &ctime );
00159                 if ( result != 0 ) {
00160                         if ( errno == ETIMEDOUT ) {
00161                                 
00162                                 return false;
00163                         } else {
00164                                 ecl_debug_throw( ipc::tryLockSemaphoreException(LOC));
00165                                 
00166                                 
00167                                 return false;
00168                         }
00169                 }
00170         #else
00171                 return trylock(); 
00172         #endif
00173         return true;
00174 }
00175 
00176 
00177 
00178 
00179 
00180 #ifdef ECL_HAS_EXCEPTIONS
00181 
00182 namespace ipc {
00183 
00184 ecl::StandardException openSemaphoreException(const char* loc) {
00185         int error_result = errno;
00186     switch ( error_result ) {
00187         case ( EACCES ) : {
00188             return StandardException(LOC,PermissionsError,"The semaphore exists, but permission to open has been denied.");
00189         }
00190         case ( EEXIST ) : {
00191             return StandardException(LOC,PermissionsError,"The semaphore already exists, so your request to explicitly create was denied.");
00192         }
00193         case ( ENOENT ) : {
00194             return StandardException(LOC,ConfigurationError,"The semaphore requested doesn't already exist (you specifically requested it to just open, not create).");
00195         }
00196         case ( ENOMEM ) : {
00197             return StandardException(LOC,MemoryError,"Insufficient memory.");
00198         }
00199         case ( EINVAL ) : {
00200             return StandardException(LOC,InvalidArgError,"Name was empty (i.e. '/'). Can also be the maximum number of semaphores has already been exceeded.");
00201         }
00202         case ( EMFILE ) : {
00203                 return StandardException(LOC,OutOfResourcesError,"This process has already exceeded the number of files/pseudofiles it is permitted to open.");
00204                 }
00205         case ( ENFILE ) : {
00206                 return StandardException(LOC,OutOfResourcesError,"This system has already exceeded the number of files/pseudofiles it is permitted to open.");
00207                 }
00208         case ( ENAMETOOLONG ) : {
00209                 return StandardException(LOC,InvalidArgError,"The semaphore name was too long.");
00210                 }
00211                 default         :
00212                 {
00213                         ostringstream ostream;
00214                         ostream << "Unknown posix error " << error_result << ": " << strerror(error_result) << ".";
00215                         return StandardException(loc, UnknownError, ostream.str());
00216                 }
00217     }
00218 }
00219 
00220 ecl::StandardException tryLockSemaphoreException(const char* loc) {
00221         int error_result = errno;
00222     switch ( error_result ) {
00223         case ( EINTR ) : {
00224             return StandardException(LOC,InterruptedError,"Waiting for the semaphore lock was interrupted by a system signal.");
00225         }
00226         case ( EINVAL ) : {
00227             return StandardException(LOC,InvalidArgError,"The semaphore was invalid or the timeout structure specified was invalid.");
00228         }
00229         case ( EAGAIN ) : {
00230             return StandardException(LOC,BlockingError,"The waiting operation could not be performed without blocking???");
00231         }
00232                 default         :
00233                 {
00234                         ostringstream ostream;
00235                         ostream << "Posix error " << error_result << ": " << strerror(error_result) << ".";
00236                         return StandardException(loc, UnknownError, ostream.str());
00237                 }
00238     }
00239 }
00240 
00241 } 
00242 
00243 #endif 
00244 
00245 }; 
00246 
00247 #endif