Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP Chris@16: #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: Chris@16: #include //O_CREAT, O_*... Chris@16: #include //close Chris@16: #include //std::string Chris@16: #include //sem_* family, SEM_VALUE_MAX Chris@16: #include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, Chris@16: #include Chris@16: Chris@16: #ifdef SEM_FAILED Chris@16: #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(SEM_FAILED)) Chris@16: #else Chris@16: #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast(-1)) Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@16: #include Chris@16: #else Chris@16: #include Chris@101: #include Chris@101: #include Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: namespace ipcdetail { Chris@16: Chris@101: #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES Chris@101: Chris@16: inline bool semaphore_open Chris@16: (sem_t *&handle, create_enum_t type, const char *origname, Chris@16: unsigned int count = 0, const permissions &perm = permissions()) Chris@16: { Chris@16: std::string name; Chris@16: #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES Chris@16: add_leading_slash(origname, name); Chris@16: #else Chris@101: create_shared_dir_cleaning_old_and_get_filepath(origname, name); Chris@16: #endif Chris@16: Chris@16: //Create new mapping Chris@16: int oflag = 0; Chris@16: switch(type){ Chris@16: case DoOpen: Chris@16: { Chris@16: //No addition Chris@16: handle = ::sem_open(name.c_str(), oflag); Chris@16: } Chris@16: break; Chris@16: case DoOpenOrCreate: Chris@16: case DoCreate: Chris@16: { Chris@16: while(1){ Chris@16: oflag = (O_CREAT | O_EXCL); Chris@16: handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count); Chris@16: if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){ Chris@16: //We can't change semaphore permissions! Chris@16: //::fchmod(handle, perm.get_permissions()); Chris@16: break; Chris@16: } Chris@16: else if(errno == EEXIST && type == DoOpenOrCreate){ Chris@16: oflag = 0; Chris@16: if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED Chris@16: || (errno != ENOENT) ){ Chris@16: break; Chris@16: } Chris@16: } Chris@16: else{ Chris@16: break; Chris@16: } Chris@16: } Chris@16: } Chris@16: break; Chris@16: default: Chris@16: { Chris@16: error_info err(other_error); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: //Check for error Chris@16: if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){ Chris@16: throw interprocess_exception(error_info(errno)); Chris@16: } Chris@16: Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline void semaphore_close(sem_t *handle) Chris@16: { Chris@16: int ret = sem_close(handle); Chris@16: if(ret != 0){ Chris@16: BOOST_ASSERT(0); Chris@16: } Chris@16: } Chris@16: Chris@16: inline bool semaphore_unlink(const char *semname) Chris@16: { Chris@16: try{ Chris@16: std::string sem_str; Chris@16: #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES Chris@16: add_leading_slash(semname, sem_str); Chris@16: #else Chris@101: shared_filepath(semname, sem_str); Chris@16: #endif Chris@16: return 0 == sem_unlink(sem_str.c_str()); Chris@16: } Chris@16: catch(...){ Chris@16: return false; Chris@16: } Chris@16: } Chris@16: Chris@101: #endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES Chris@101: Chris@101: #ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES Chris@101: Chris@16: inline void semaphore_init(sem_t *handle, unsigned int initialCount) Chris@16: { Chris@16: int ret = sem_init(handle, 1, initialCount); Chris@16: //According to SUSV3 version 2003 edition, the return value of a successful Chris@16: //sem_init call is not defined, but -1 is returned on failure. Chris@16: //In the future, a successful call might be required to return 0. Chris@16: if(ret == -1){ Chris@101: error_info err = system_error_code(); Chris@101: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: inline void semaphore_destroy(sem_t *handle) Chris@16: { Chris@16: int ret = sem_destroy(handle); Chris@16: if(ret != 0){ Chris@16: BOOST_ASSERT(0); Chris@16: } Chris@16: } Chris@16: Chris@101: #endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES Chris@101: Chris@16: inline void semaphore_post(sem_t *handle) Chris@16: { Chris@16: int ret = sem_post(handle); Chris@16: if(ret != 0){ Chris@101: error_info err = system_error_code(); Chris@101: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: inline void semaphore_wait(sem_t *handle) Chris@16: { Chris@16: int ret = sem_wait(handle); Chris@16: if(ret != 0){ Chris@101: error_info err = system_error_code(); Chris@101: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: inline bool semaphore_try_wait(sem_t *handle) Chris@16: { Chris@16: int res = sem_trywait(handle); Chris@16: if(res == 0) Chris@16: return true; Chris@16: if(system_error_code() == EAGAIN){ Chris@16: return false; Chris@16: } Chris@101: error_info err = system_error_code(); Chris@101: throw interprocess_exception(err); Chris@16: } Chris@16: Chris@101: #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@101: Chris@101: struct semaphore_wrapper_try_wrapper Chris@101: { Chris@101: explicit semaphore_wrapper_try_wrapper(sem_t *handle) Chris@101: : m_handle(handle) Chris@101: {} Chris@101: Chris@101: void wait() Chris@101: { semaphore_wait(m_handle); } Chris@101: Chris@101: bool try_wait() Chris@101: { return semaphore_try_wait(m_handle); } Chris@101: Chris@101: private: Chris@101: sem_t *m_handle; Chris@101: }; Chris@101: Chris@101: #endif Chris@101: Chris@16: inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time) Chris@16: { Chris@101: #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@101: //Posix does not support infinity absolute time so handle it here Chris@16: if(abs_time == boost::posix_time::pos_infin){ Chris@16: semaphore_wait(handle); Chris@16: return true; Chris@16: } Chris@101: Chris@16: timespec tspec = ptime_to_timespec(abs_time); Chris@16: for (;;){ Chris@16: int res = sem_timedwait(handle, &tspec); Chris@16: if(res == 0) Chris@16: return true; Chris@16: if (res > 0){ Chris@16: //buggy glibc, copy the returned error code to errno Chris@16: errno = res; Chris@16: } Chris@16: if(system_error_code() == ETIMEDOUT){ Chris@16: return false; Chris@16: } Chris@101: error_info err = system_error_code(); Chris@101: throw interprocess_exception(err); Chris@16: } Chris@16: return false; Chris@16: #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@101: Chris@101: semaphore_wrapper_try_wrapper swtw(handle); Chris@101: ipcdetail::lock_to_wait lw(swtw); Chris@101: return ipcdetail::try_based_timed_lock(lw, abs_time); Chris@101: Chris@16: #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@16: } Chris@16: Chris@16: } //namespace ipcdetail { Chris@16: } //namespace interprocess { Chris@16: } //namespace boost { Chris@16: Chris@16: #endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP