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@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #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@16: #include Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: namespace ipcdetail { Chris@16: 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@16: create_tmp_and_clean_old_and_get_filename(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@16: tmp_filename(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@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@16: throw interprocess_exception(system_error_code()); 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@16: inline void semaphore_post(sem_t *handle) Chris@16: { Chris@16: int ret = sem_post(handle); Chris@16: if(ret != 0){ Chris@16: throw interprocess_exception(system_error_code()); 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@16: throw interprocess_exception(system_error_code()); 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@16: throw interprocess_exception(system_error_code()); Chris@16: return false; Chris@16: } Chris@16: Chris@16: inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time) Chris@16: { Chris@16: if(abs_time == boost::posix_time::pos_infin){ Chris@16: semaphore_wait(handle); Chris@16: return true; Chris@16: } Chris@16: #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS 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@16: throw interprocess_exception(system_error_code()); Chris@16: } Chris@16: return false; Chris@16: #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS Chris@16: boost::posix_time::ptime now; Chris@16: spin_wait swait; Chris@16: do{ Chris@16: if(semaphore_try_wait(handle)) Chris@16: return true; Chris@16: swait.yield(); Chris@16: }while((now = microsec_clock::universal_time()) < abs_time); Chris@16: return false; 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