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