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