]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / interprocess / sync / posix / semaphore_wrapper.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
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)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
12 #define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
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>
28
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>
35
36 #ifdef SEM_FAILED
37 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
38 #else
39 #define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
40 #endif
41
42 #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
43 #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
44 #else
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>
48 #endif
49
50 namespace boost {
51 namespace interprocess {
52 namespace ipcdetail {
53
54 #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
55
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())
59 {
60 std::string name;
61 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
62 add_leading_slash(origname, name);
63 #else
64 create_shared_dir_cleaning_old_and_get_filepath(origname, name);
65 #endif
66
67 //Create new mapping
68 int oflag = 0;
69 switch(type){
70 case DoOpen:
71 {
72 //No addition
73 handle = ::sem_open(name.c_str(), oflag);
74 }
75 break;
76 case DoOpenOrCreate:
77 case DoCreate:
78 {
79 while(1){
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());
85 break;
86 }
87 else if(errno == EEXIST && type == DoOpenOrCreate){
88 oflag = 0;
89 if( (handle = ::sem_open(name.c_str(), oflag)) != BOOST_INTERPROCESS_POSIX_SEM_FAILED
90 || (errno != ENOENT) ){
91 break;
92 }
93 }
94 else{
95 break;
96 }
97 }
98 }
99 break;
100 default:
101 {
102 error_info err(other_error);
103 throw interprocess_exception(err);
104 }
105 }
106
107 //Check for error
108 if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
109 throw interprocess_exception(error_info(errno));
110 }
111
112 return true;
113 }
114
115 inline void semaphore_close(sem_t *handle)
116 {
117 int ret = sem_close(handle);
118 if(ret != 0){
119 BOOST_ASSERT(0);
120 }
121 }
122
123 inline bool semaphore_unlink(const char *semname)
124 {
125 try{
126 std::string sem_str;
127 #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
128 add_leading_slash(semname, sem_str);
129 #else
130 shared_filepath(semname, sem_str);
131 #endif
132 return 0 == sem_unlink(sem_str.c_str());
133 }
134 catch(...){
135 return false;
136 }
137 }
138
139 #endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
140
141 #ifdef BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
142
143 inline void semaphore_init(sem_t *handle, unsigned int initialCount)
144 {
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.
149 if(ret == -1){
150 error_info err = system_error_code();
151 throw interprocess_exception(err);
152 }
153 }
154
155 inline void semaphore_destroy(sem_t *handle)
156 {
157 int ret = sem_destroy(handle);
158 if(ret != 0){
159 BOOST_ASSERT(0);
160 }
161 }
162
163 #endif //BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES
164
165 inline void semaphore_post(sem_t *handle)
166 {
167 int ret = sem_post(handle);
168 if(ret != 0){
169 error_info err = system_error_code();
170 throw interprocess_exception(err);
171 }
172 }
173
174 inline void semaphore_wait(sem_t *handle)
175 {
176 int ret = sem_wait(handle);
177 if(ret != 0){
178 error_info err = system_error_code();
179 throw interprocess_exception(err);
180 }
181 }
182
183 inline bool semaphore_try_wait(sem_t *handle)
184 {
185 int res = sem_trywait(handle);
186 if(res == 0)
187 return true;
188 if(system_error_code() == EAGAIN){
189 return false;
190 }
191 error_info err = system_error_code();
192 throw interprocess_exception(err);
193 }
194
195 #ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
196
197 struct semaphore_wrapper_try_wrapper
198 {
199 explicit semaphore_wrapper_try_wrapper(sem_t *handle)
200 : m_handle(handle)
201 {}
202
203 void wait()
204 { semaphore_wait(m_handle); }
205
206 bool try_wait()
207 { return semaphore_try_wait(m_handle); }
208
209 private:
210 sem_t *m_handle;
211 };
212
213 #endif
214
215 inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
216 {
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);
221 return true;
222 }
223
224 timespec tspec = ptime_to_timespec(abs_time);
225 for (;;){
226 int res = sem_timedwait(handle, &tspec);
227 if(res == 0)
228 return true;
229 if (res > 0){
230 //buggy glibc, copy the returned error code to errno
231 errno = res;
232 }
233 if(system_error_code() == ETIMEDOUT){
234 return false;
235 }
236 error_info err = system_error_code();
237 throw interprocess_exception(err);
238 }
239 return false;
240 #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
241
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);
245
246 #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
247 }
248
249 } //namespace ipcdetail {
250 } //namespace interprocess {
251 } //namespace boost {
252
253 #endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP