Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-07 08:22:04

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
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    //Create new mapping
0069    int oflag = 0;
0070    switch(type){
0071       case DoOpen:
0072       {
0073          //No addition
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                //We can't change semaphore permissions!
0087                //::fchmod(handle, perm.get_permissions());
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    //Check for error
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    //Cygwin returns EINVAL in some valid use cases
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   //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
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    //According to SUSV3 version 2003 edition, the return value of a successful
0156    //sem_init call is not defined, but -1 is returned on failure.
0157    //In the future, a successful call might be required to return 0.
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   //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
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    //Posix does not support infinity absolute time so handle it here
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          //buggy glibc, copy the returned error code to errno
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 //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
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   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0257 }
0258 
0259 }  //namespace ipcdetail {
0260 }  //namespace interprocess {
0261 }  //namespace boost {
0262 
0263 #endif   //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP