File indexing completed on 2025-09-17 08:34:11
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/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 = BOOST_INTERPROCESS_EINTR_RETRY(sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED, ::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 = BOOST_INTERPROCESS_EINTR_RETRY
0082 ( sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED
0083 , ::sem_open(name.c_str(), oflag, perm.get_permissions(), count));
0084 if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
0085
0086
0087 break;
0088 }
0089 else if(errno == EEXIST && type == DoOpenOrCreate){
0090 oflag = 0;
0091 if( (handle = BOOST_INTERPROCESS_EINTR_RETRY
0092 (sem_t*, BOOST_INTERPROCESS_POSIX_SEM_FAILED, ::sem_open(name.c_str(), oflag)))
0093 != BOOST_INTERPROCESS_POSIX_SEM_FAILED
0094 || (errno != ENOENT) ){
0095 break;
0096 }
0097 }
0098 else{
0099 break;
0100 }
0101 }
0102 }
0103 break;
0104 default:
0105 {
0106 error_info err(other_error);
0107 throw interprocess_exception(err);
0108 }
0109 }
0110
0111
0112 if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
0113 throw interprocess_exception(error_info(errno));
0114 }
0115
0116 return true;
0117 }
0118
0119 inline void semaphore_close(sem_t *handle)
0120 {
0121 int ret = sem_close(handle);
0122 #ifdef __CYGWIN__
0123
0124 if (ret == -1 && errno == EINVAL)
0125 ret = 0;
0126 #endif
0127 BOOST_ASSERT(ret == 0);
0128 (void)ret;
0129 }
0130
0131 inline bool semaphore_unlink(const char *semname)
0132 {
0133 BOOST_INTERPROCESS_TRY{
0134 std::string sem_str;
0135 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
0136 add_leading_slash(semname, sem_str);
0137 #else
0138 shared_filepath(semname, sem_str);
0139 #endif
0140 return 0 == sem_unlink(sem_str.c_str());
0141 }
0142 BOOST_INTERPROCESS_CATCH(...){
0143 return false;
0144 } BOOST_INTERPROCESS_CATCH_END
0145 }
0146
0147 #endif
0148
0149 #ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
0150
0151 inline void semaphore_init(sem_t *handle, unsigned int initialCount)
0152 {
0153 int ret = sem_init(handle, 1, initialCount);
0154
0155
0156
0157 if(ret == -1){
0158 error_info err = system_error_code();
0159 throw interprocess_exception(err);
0160 }
0161 }
0162
0163 inline void semaphore_destroy(sem_t *handle)
0164 {
0165 int ret = sem_destroy(handle);
0166 if(ret != 0){
0167 BOOST_ASSERT(0);
0168 }
0169 }
0170
0171 #endif
0172
0173 inline void semaphore_post(sem_t *handle)
0174 {
0175 int ret = sem_post(handle);
0176 if(ret != 0){
0177 error_info err = system_error_code();
0178 throw interprocess_exception(err);
0179 }
0180 }
0181
0182 inline void semaphore_wait(sem_t *handle)
0183 {
0184 int ret = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_wait(handle));
0185 if(ret != 0){
0186 error_info err = system_error_code();
0187 throw interprocess_exception(err);
0188 }
0189 }
0190
0191 inline bool semaphore_try_wait(sem_t *handle)
0192 {
0193 int res = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_trywait(handle));
0194 if(res == 0)
0195 return true;
0196 if(system_error_code() == EAGAIN){
0197 return false;
0198 }
0199 error_info err = system_error_code();
0200 throw interprocess_exception(err);
0201 }
0202
0203 #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0204
0205 struct semaphore_wrapper_try_wrapper
0206 {
0207 explicit semaphore_wrapper_try_wrapper(sem_t *handle)
0208 : m_handle(handle)
0209 {}
0210
0211 void wait()
0212 { semaphore_wait(m_handle); }
0213
0214 bool try_wait()
0215 { return semaphore_try_wait(m_handle); }
0216
0217 private:
0218 sem_t *m_handle;
0219 };
0220
0221 #endif
0222
0223 template<class TimePoint>
0224 inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time)
0225 {
0226 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0227
0228 if(ipcdetail::is_pos_infinity(abs_time)){
0229 semaphore_wait(handle);
0230 return true;
0231 }
0232
0233 timespec tspec = timepoint_to_timespec(abs_time);
0234 for (;;){
0235 int res = BOOST_INTERPROCESS_EINTR_RETRY(int, -1, sem_timedwait(handle, &tspec));
0236 if(res == 0)
0237 return true;
0238 if (res > 0){
0239
0240 errno = res;
0241 }
0242 if(system_error_code() == ETIMEDOUT){
0243 return false;
0244 }
0245 error_info err = system_error_code();
0246 throw interprocess_exception(err);
0247 }
0248 return false;
0249 #else
0250
0251 semaphore_wrapper_try_wrapper swtw(handle);
0252 ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
0253 return ipcdetail::try_based_timed_lock(lw, abs_time);
0254
0255 #endif
0256 }
0257
0258 }
0259 }
0260 }
0261
0262 #endif