Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:34:11

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 #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    //Create new mapping
0068    int oflag = 0;
0069    switch(type){
0070       case DoOpen:
0071       {
0072          //No addition
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                //We can't change semaphore permissions!
0086                //::fchmod(handle, perm.get_permissions());
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    //Check for error
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    //Cygwin returns EINVAL in some valid use cases
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   //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
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    //According to SUSV3 version 2003 edition, the return value of a successful
0155    //sem_init call is not defined, but -1 is returned on failure.
0156    //In the future, a successful call might be required to return 0.
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   //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
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    //Posix does not support infinity absolute time so handle it here
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          //buggy glibc, copy the returned error code to errno
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 //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
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   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
0256 }
0257 
0258 }  //namespace ipcdetail {
0259 }  //namespace interprocess {
0260 }  //namespace boost {
0261 
0262 #endif   //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP