1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/interprocess for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
12 #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
23 #include <boost/interprocess/exceptions.hpp>
24 #include <boost/interprocess/creation_tags.hpp>
25 #include <boost/interprocess/detail/os_file_functions.hpp>
26 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
27 #include <boost/interprocess/permissions.hpp>
29 #include <fcntl.h> //O_CREAT, O_*...
30 #include <unistd.h> //close
31 #include <string> //std::string
32 #include <semaphore.h> //sem_* family, SEM_VALUE_MAX
33 #include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
34 #include <boost/assert.hpp>
37 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
39 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
42 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
43 #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
45 #include <boost/interprocess/detail/os_thread_functions.hpp>
46 #include <boost/interprocess/sync/detail/locks.hpp>
47 #include <boost/interprocess/sync/detail/common_algorithms.hpp>
51 namespace interprocess {
54 #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
56 inline bool semaphore_open
57 (sem_t *&handle, create_enum_t type, const char *origname,
58 unsigned int count = 0, const permissions &perm = permissions())
61 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
62 add_leading_slash(origname, name);
64 create_shared_dir_cleaning_old_and_get_filepath(origname, name);
73 handle = ::sem_open(name.c_str(), oflag);
80 oflag = (O_CREAT | O_EXCL);
81 handle = ::sem_open(name.c_str(), oflag, perm.get_permissions(), count);
82 if(handle != BOOST_INTERPROCESS_POSIX_SEM_FAILED){
83 //We can't change semaphore permissions!
84 //::fchmod(handle, perm.get_permissions());
87 else if(errno == EEXIST && type == DoOpenOrCreate){
89 if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
90 || (errno != ENOENT) ){
102 error_info err(other_error);
103 throw interprocess_exception(err);
108 if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
109 throw interprocess_exception(error_info(errno));
115 inline void semaphore_close(sem_t *handle)
117 int ret = sem_close(handle);
123 inline bool semaphore_unlink(const char *semname)
127 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
128 add_leading_slash(semname, sem_str);
130 shared_filepath(semname, sem_str);
132 return 0 == sem_unlink(sem_str.c_str());
139 #endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
141 #ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
143 inline void semaphore_init(sem_t *handle, unsigned int initialCount)
145 int ret = sem_init(handle, 1, initialCount);
146 //According to SUSV3 version 2003 edition, the return value of a successful
147 //sem_init call is not defined, but -1 is returned on failure.
148 //In the future, a successful call might be required to return 0.
150 error_info err = system_error_code();
151 throw interprocess_exception(err);
155 inline void semaphore_destroy(sem_t *handle)
157 int ret = sem_destroy(handle);
163 #endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
165 inline void semaphore_post(sem_t *handle)
167 int ret = sem_post(handle);
169 error_info err = system_error_code();
170 throw interprocess_exception(err);
174 inline void semaphore_wait(sem_t *handle)
176 int ret = sem_wait(handle);
178 error_info err = system_error_code();
179 throw interprocess_exception(err);
183 inline bool semaphore_try_wait(sem_t *handle)
185 int res = sem_trywait(handle);
188 if(system_error_code() == EAGAIN){
191 error_info err = system_error_code();
192 throw interprocess_exception(err);
195 #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
197 struct semaphore_wrapper_try_wrapper
199 explicit semaphore_wrapper_try_wrapper(sem_t *handle)
204 { semaphore_wait(m_handle); }
207 { return semaphore_try_wait(m_handle); }
215 inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
217 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
218 //Posix does not support infinity absolute time so handle it here
219 if(abs_time == boost::posix_time::pos_infin){
220 semaphore_wait(handle);
224 timespec tspec = ptime_to_timespec(abs_time);
226 int res = sem_timedwait(handle, &tspec);
230 //buggy glibc, copy the returned error code to errno
233 if(system_error_code() == ETIMEDOUT){
236 error_info err = system_error_code();
237 throw interprocess_exception(err);
240 #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
242 semaphore_wrapper_try_wrapper swtw(handle);
243 ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
244 return ipcdetail::try_based_timed_lock(lw, abs_time);
246 #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
249 } //namespace ipcdetail {
250 } //namespace interprocess {
251 } //namespace boost {
253 #endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP