File indexing completed on 2025-01-18 09:38:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
0012 #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/interprocess/exceptions.hpp>
0023 #include <boost/interprocess/creation_tags.hpp>
0024 #include <boost/interprocess/detail/os_file_functions.hpp>
0025 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
0026 #include <boost/interprocess/detail/timed_utils.hpp>
0027 #include <boost/interprocess/permissions.hpp>
0028
0029 #include <fcntl.h> //O_CREAT, O_*...
0030 #include <unistd.h> //close
0031 #include <string> //std::string
0032 #include <semaphore.h> //sem_* family, SEM_VALUE_MAX
0033 #include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
0034 #include <boost/assert.hpp>
0035
0036 #ifdef SEM_FAILED
0037 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
0038 #else
0039 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
0040 #endif
0041
0042 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0043 #include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
0044 #else
0045 #include <boost/interprocess/detail/os_thread_functions.hpp>
0046 #include <boost/interprocess/sync/detail/locks.hpp>
0047 #include <boost/interprocess/sync/detail/common_algorithms.hpp>
0048 #endif
0049
0050 namespace boost {
0051 namespace interprocess {
0052 namespace ipcdetail {
0053
0054 #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
0055
0056 inline bool semaphore_open
0057 (sem_t *&handle, create_enum_t type, const char *origname,
0058 unsigned int count = 0, const permissions &perm = permissions())
0059 {
0060 std::string name;
0061 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
0062 add_leading_slash(origname, name);
0063 #else
0064 create_shared_dir_cleaning_old_and_get_filepath(origname, name);
0065 #endif
0066
0067
0068 int oflag = 0;
0069 switch(type){
0070 case DoOpen:
0071 {
0072
0073 handle = ::sem_open(name.c_str(), oflag);
0074 }
0075 break;
0076 case DoOpenOrCreate:
0077 case DoCreate:
0078 {
0079 while(1){
0080 oflag = (O_CREAT | O_EXCL);
0081 handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count);
0082 if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
0083
0084
0085 break;
0086 }
0087 else if(errno == EEXIST && type == DoOpenOrCreate){
0088 oflag = 0;
0089 if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
0090 || (errno != ENOENT) ){
0091 break;
0092 }
0093 }
0094 else{
0095 break;
0096 }
0097 }
0098 }
0099 break;
0100 default:
0101 {
0102 error_info err(other_error);
0103 throw interprocess_exception(err);
0104 }
0105 }
0106
0107
0108 if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
0109 throw interprocess_exception(error_info(errno));
0110 }
0111
0112 return true;
0113 }
0114
0115 inline void semaphore_close(sem_t *handle)
0116 {
0117 int ret = sem_close(handle);
0118 if(ret != 0){
0119 BOOST_ASSERT(0);
0120 }
0121 }
0122
0123 inline bool semaphore_unlink(const char *semname)
0124 {
0125 BOOST_TRY{
0126 std::string sem_str;
0127 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
0128 add_leading_slash(semname, sem_str);
0129 #else
0130 shared_filepath(semname, sem_str);
0131 #endif
0132 return 0 == sem_unlink(sem_str.c_str());
0133 }
0134 BOOST_CATCH(...){
0135 return false;
0136 } BOOST_CATCH_END
0137 }
0138
0139 #endif
0140
0141 #ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
0142
0143 inline void semaphore_init(sem_t *handle, unsigned int initialCount)
0144 {
0145 int ret = sem_init(handle, 1, initialCount);
0146
0147
0148
0149 if(ret == -1){
0150 error_info err = system_error_code();
0151 throw interprocess_exception(err);
0152 }
0153 }
0154
0155 inline void semaphore_destroy(sem_t *handle)
0156 {
0157 int ret = sem_destroy(handle);
0158 if(ret != 0){
0159 BOOST_ASSERT(0);
0160 }
0161 }
0162
0163 #endif
0164
0165 inline void semaphore_post(sem_t *handle)
0166 {
0167 int ret = sem_post(handle);
0168 if(ret != 0){
0169 error_info err = system_error_code();
0170 throw interprocess_exception(err);
0171 }
0172 }
0173
0174 inline void semaphore_wait(sem_t *handle)
0175 {
0176 int ret = sem_wait(handle);
0177 if(ret != 0){
0178 error_info err = system_error_code();
0179 throw interprocess_exception(err);
0180 }
0181 }
0182
0183 inline bool semaphore_try_wait(sem_t *handle)
0184 {
0185 int res = sem_trywait(handle);
0186 if(res == 0)
0187 return true;
0188 if(system_error_code() == EAGAIN){
0189 return false;
0190 }
0191 error_info err = system_error_code();
0192 throw interprocess_exception(err);
0193 }
0194
0195 #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0196
0197 struct semaphore_wrapper_try_wrapper
0198 {
0199 explicit semaphore_wrapper_try_wrapper(sem_t *handle)
0200 : m_handle(handle)
0201 {}
0202
0203 void wait()
0204 { semaphore_wait(m_handle); }
0205
0206 bool try_wait()
0207 { return semaphore_try_wait(m_handle); }
0208
0209 private:
0210 sem_t *m_handle;
0211 };
0212
0213 #endif
0214
0215 template<class TimePoint>
0216 inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time)
0217 {
0218 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0219
0220 if(ipcdetail::is_pos_infinity(abs_time)){
0221 semaphore_wait(handle);
0222 return true;
0223 }
0224
0225 timespec tspec = timepoint_to_timespec(abs_time);
0226 for (;;){
0227 int res = sem_timedwait(handle, &tspec);
0228 if(res == 0)
0229 return true;
0230 if (res > 0){
0231
0232 errno = res;
0233 }
0234 if(system_error_code() == ETIMEDOUT){
0235 return false;
0236 }
0237 error_info err = system_error_code();
0238 throw interprocess_exception(err);
0239 }
0240 return false;
0241 #else
0242
0243 semaphore_wrapper_try_wrapper swtw(handle);
0244 ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
0245 return ipcdetail::try_based_timed_lock(lw, abs_time);
0246
0247 #endif
0248 }
0249
0250 }
0251 }
0252 }
0253
0254 #endif