Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/interprocess for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
|
Chris@16
|
12 #define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
|
Chris@16
|
13
|
Chris@101
|
14 #ifndef BOOST_CONFIG_HPP
|
Chris@101
|
15 # include <boost/config.hpp>
|
Chris@101
|
16 #endif
|
Chris@101
|
17 #
|
Chris@101
|
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@101
|
19 # pragma once
|
Chris@101
|
20 #endif
|
Chris@101
|
21
|
Chris@16
|
22 #include <boost/interprocess/detail/config_begin.hpp>
|
Chris@16
|
23 #include <boost/interprocess/detail/workaround.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #if defined(BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
26 #error "This header can't be used in Windows operating systems"
|
Chris@16
|
27 #endif
|
Chris@16
|
28
|
Chris@101
|
29 #include <boost/move/utility_core.hpp>
|
Chris@16
|
30 #include <boost/interprocess/creation_tags.hpp>
|
Chris@16
|
31 #include <boost/interprocess/exceptions.hpp>
|
Chris@16
|
32 #include <boost/interprocess/detail/utilities.hpp>
|
Chris@16
|
33 #include <boost/interprocess/detail/os_file_functions.hpp>
|
Chris@16
|
34 #include <boost/interprocess/interprocess_fwd.hpp>
|
Chris@16
|
35 #include <boost/interprocess/exceptions.hpp>
|
Chris@16
|
36 #include <boost/interprocess/sync/xsi/basic_xsi_semaphore.hpp>
|
Chris@101
|
37 #include <boost/interprocess/detail/simple_swap.hpp>
|
Chris@101
|
38
|
Chris@16
|
39 #include <cstddef>
|
Chris@16
|
40 #include <boost/assert.hpp>
|
Chris@16
|
41 #include <boost/cstdint.hpp>
|
Chris@16
|
42 #include <string>
|
Chris@101
|
43
|
Chris@16
|
44
|
Chris@16
|
45 //!\file
|
Chris@16
|
46 //!Describes a class representing a xsi-based named_mutex.
|
Chris@16
|
47
|
Chris@16
|
48 namespace boost {
|
Chris@16
|
49 namespace interprocess {
|
Chris@16
|
50
|
Chris@16
|
51 //!A class that wraps a XSI (System V)-based named semaphore
|
Chris@16
|
52 //!that undoes the operation if the process crashes.
|
Chris@16
|
53 class xsi_named_mutex
|
Chris@16
|
54 {
|
Chris@101
|
55 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
56 //Non-copyable and non-assignable
|
Chris@16
|
57 xsi_named_mutex(xsi_named_mutex &);
|
Chris@16
|
58 xsi_named_mutex &operator=(xsi_named_mutex &);
|
Chris@101
|
59 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
60
|
Chris@16
|
61 public:
|
Chris@16
|
62 BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex)
|
Chris@16
|
63
|
Chris@16
|
64 //!Default constructor.
|
Chris@16
|
65 //!Represents an empty xsi_named_mutex.
|
Chris@16
|
66 xsi_named_mutex();
|
Chris@16
|
67
|
Chris@16
|
68 //!Tries to create a new XSI-based named mutex with a key obtained from a call to ftok (with path
|
Chris@16
|
69 //!"path" and id "id"), and permissions "perm".
|
Chris@16
|
70 //!If the named mutex previously exists, it tries to open it.
|
Chris@16
|
71 //!Otherwise throws an error.
|
Chris@16
|
72 xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666)
|
Chris@16
|
73 { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, path, id, perm); }
|
Chris@16
|
74
|
Chris@16
|
75 //!Moves the ownership of "moved"'s named mutex to *this.
|
Chris@16
|
76 //!After the call, "moved" does not represent any named mutex
|
Chris@16
|
77 //!Does not throw
|
Chris@16
|
78 xsi_named_mutex(BOOST_RV_REF(xsi_named_mutex) moved)
|
Chris@16
|
79 { this->swap(moved); }
|
Chris@16
|
80
|
Chris@16
|
81 //!Moves the ownership of "moved"'s named mutex to *this.
|
Chris@16
|
82 //!After the call, "moved" does not represent any named mutex.
|
Chris@16
|
83 //!Does not throw
|
Chris@16
|
84 xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved)
|
Chris@16
|
85 {
|
Chris@16
|
86 xsi_named_mutex tmp(boost::move(moved));
|
Chris@16
|
87 this->swap(tmp);
|
Chris@16
|
88 return *this;
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 //!Swaps two xsi_named_mutex. Does not throw
|
Chris@16
|
92 void swap(xsi_named_mutex &other);
|
Chris@16
|
93
|
Chris@16
|
94 //!Destroys *this. The named mutex is still valid after
|
Chris@16
|
95 //!destruction. use remove() to destroy the named mutex.
|
Chris@16
|
96 ~xsi_named_mutex();
|
Chris@16
|
97
|
Chris@16
|
98 //!Returns the path used to construct the
|
Chris@16
|
99 //!named mutex.
|
Chris@16
|
100 const char *get_path() const;
|
Chris@16
|
101
|
Chris@16
|
102 //!Returns access
|
Chris@16
|
103 //!permissions
|
Chris@16
|
104 int get_permissions() const;
|
Chris@16
|
105
|
Chris@16
|
106 //!Returns the mapping handle.
|
Chris@16
|
107 //!Never throws
|
Chris@16
|
108 mapping_handle_t get_mapping_handle() const;
|
Chris@16
|
109
|
Chris@16
|
110 //!Erases a XSI-based named mutex from the system.
|
Chris@16
|
111 //!Returns false on error. Never throws
|
Chris@16
|
112 bool remove();
|
Chris@16
|
113
|
Chris@16
|
114 void lock();
|
Chris@16
|
115
|
Chris@16
|
116 void unlock();
|
Chris@16
|
117
|
Chris@101
|
118 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
119 private:
|
Chris@16
|
120
|
Chris@16
|
121 //!Closes a previously opened file mapping. Never throws.
|
Chris@16
|
122 void priv_close();
|
Chris@16
|
123
|
Chris@16
|
124 //!Closes a previously opened file mapping. Never throws.
|
Chris@16
|
125 bool priv_open_or_create( ipcdetail::create_enum_t type
|
Chris@16
|
126 , const char *path
|
Chris@16
|
127 , boost::uint8_t id
|
Chris@16
|
128 , int perm);
|
Chris@16
|
129 int m_semid;
|
Chris@16
|
130 key_t m_key;
|
Chris@16
|
131 boost::uint8_t m_id;
|
Chris@16
|
132 int m_perm;
|
Chris@16
|
133 std::string m_path;
|
Chris@101
|
134 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
135 };
|
Chris@16
|
136
|
Chris@101
|
137 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
138
|
Chris@16
|
139 inline xsi_named_mutex::xsi_named_mutex()
|
Chris@16
|
140 : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path()
|
Chris@16
|
141 {}
|
Chris@16
|
142
|
Chris@16
|
143 inline xsi_named_mutex::~xsi_named_mutex()
|
Chris@16
|
144 { this->priv_close(); }
|
Chris@16
|
145
|
Chris@16
|
146 inline const char *xsi_named_mutex::get_path() const
|
Chris@16
|
147 { return m_path.c_str(); }
|
Chris@16
|
148
|
Chris@16
|
149 inline void xsi_named_mutex::swap(xsi_named_mutex &other)
|
Chris@16
|
150 {
|
Chris@101
|
151 (simple_swap)(m_key, other.m_key);
|
Chris@101
|
152 (simple_swap)(m_id, other.m_id);
|
Chris@101
|
153 (simple_swap)(m_semid, other.m_semid);
|
Chris@101
|
154 (simple_swap)(m_perm, other.m_perm);
|
Chris@16
|
155 m_path.swap(other.m_path);
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const
|
Chris@16
|
159 { mapping_handle_t mhnd = { m_semid, true}; return mhnd; }
|
Chris@16
|
160
|
Chris@16
|
161 inline int xsi_named_mutex::get_permissions() const
|
Chris@16
|
162 { return m_perm; }
|
Chris@16
|
163
|
Chris@16
|
164 inline bool xsi_named_mutex::priv_open_or_create
|
Chris@16
|
165 (ipcdetail::create_enum_t type, const char *path, boost::uint8_t id, int perm)
|
Chris@16
|
166 {
|
Chris@16
|
167 key_t key;
|
Chris@16
|
168 if(path){
|
Chris@16
|
169 key = ::ftok(path, id);
|
Chris@16
|
170 if(((key_t)-1) == key){
|
Chris@16
|
171 error_info err = system_error_code();
|
Chris@16
|
172 throw interprocess_exception(err);
|
Chris@16
|
173 }
|
Chris@16
|
174 }
|
Chris@16
|
175 else{
|
Chris@16
|
176 key = IPC_PRIVATE;
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 perm &= 0x01FF;
|
Chris@16
|
180
|
Chris@16
|
181 int semid;
|
Chris@16
|
182 if(!xsi::simple_sem_open_or_create(key, 1, semid, perm)){
|
Chris@16
|
183 error_info err = system_error_code();
|
Chris@16
|
184 throw interprocess_exception(err);
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 m_perm = perm;
|
Chris@16
|
188 m_semid = semid;
|
Chris@16
|
189 m_path = path ? path : "";
|
Chris@16
|
190 m_id = id;
|
Chris@16
|
191 m_key = key;
|
Chris@16
|
192
|
Chris@16
|
193 return true;
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 inline void xsi_named_mutex::priv_close()
|
Chris@16
|
197 {
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 inline void xsi_named_mutex::lock()
|
Chris@16
|
201 {
|
Chris@16
|
202 if(!xsi::simple_sem_op(m_semid, -1)){
|
Chris@16
|
203 error_info err = system_error_code();
|
Chris@16
|
204 throw interprocess_exception(err);
|
Chris@16
|
205 }
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 inline void xsi_named_mutex::unlock()
|
Chris@16
|
209 {
|
Chris@16
|
210 bool success = xsi::simple_sem_op(m_semid, 1);
|
Chris@16
|
211 (void)success;
|
Chris@16
|
212 BOOST_ASSERT(success);
|
Chris@16
|
213 }
|
Chris@16
|
214
|
Chris@16
|
215 inline bool xsi_named_mutex::remove()
|
Chris@16
|
216 {
|
Chris@16
|
217 if(m_semid != -1){
|
Chris@16
|
218 int ret = ::semctl(m_semid, IPC_RMID, 0);
|
Chris@16
|
219 if(-1 == ret)
|
Chris@16
|
220 return false;
|
Chris@16
|
221 //Now put it in default-constructed state
|
Chris@16
|
222 m_semid = -1;
|
Chris@16
|
223 m_key = -1;
|
Chris@16
|
224 m_id = 0;
|
Chris@16
|
225 m_perm = 0;
|
Chris@16
|
226 m_path.clear();
|
Chris@16
|
227 }
|
Chris@16
|
228 return false;
|
Chris@16
|
229 }
|
Chris@16
|
230
|
Chris@101
|
231 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
232
|
Chris@16
|
233 } //namespace interprocess {
|
Chris@16
|
234 } //namespace boost {
|
Chris@16
|
235
|
Chris@16
|
236 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
237
|
Chris@16
|
238 #endif //BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP
|