Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2005-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_WINDOWS_SHARED_MEMORY_HPP
|
Chris@16
|
12 #define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_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@101
|
24
|
Chris@16
|
25 #include <boost/interprocess/permissions.hpp>
|
Chris@101
|
26 #include <boost/interprocess/detail/simple_swap.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #if !defined(BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
29 #error "This header can only be used in Windows operating systems"
|
Chris@16
|
30 #endif
|
Chris@16
|
31
|
Chris@16
|
32 #include <boost/interprocess/creation_tags.hpp>
|
Chris@16
|
33 #include <boost/interprocess/exceptions.hpp>
|
Chris@16
|
34 #include <boost/interprocess/detail/utilities.hpp>
|
Chris@16
|
35 #include <boost/interprocess/detail/os_file_functions.hpp>
|
Chris@16
|
36 #include <boost/interprocess/interprocess_fwd.hpp>
|
Chris@16
|
37 #include <boost/interprocess/exceptions.hpp>
|
Chris@16
|
38 #include <boost/interprocess/detail/win32_api.hpp>
|
Chris@16
|
39 #include <cstddef>
|
Chris@16
|
40 #include <boost/cstdint.hpp>
|
Chris@16
|
41 #include <string>
|
Chris@16
|
42
|
Chris@16
|
43 //!\file
|
Chris@16
|
44 //!Describes a class representing a native windows shared memory.
|
Chris@16
|
45
|
Chris@16
|
46 namespace boost {
|
Chris@16
|
47 namespace interprocess {
|
Chris@16
|
48
|
Chris@16
|
49 //!A class that wraps the native Windows shared memory
|
Chris@16
|
50 //!that is implemented as a file mapping of the paging file.
|
Chris@16
|
51 //!Unlike shared_memory_object, windows_shared_memory has
|
Chris@16
|
52 //!no kernel persistence and the shared memory is destroyed
|
Chris@16
|
53 //!when all processes destroy all their windows_shared_memory
|
Chris@16
|
54 //!objects and mapped regions for the same shared memory
|
Chris@16
|
55 //!or the processes end/crash.
|
Chris@16
|
56 //!
|
Chris@16
|
57 //!Warning: Windows native shared memory and interprocess portable
|
Chris@16
|
58 //!shared memory (boost::interprocess::shared_memory_object)
|
Chris@16
|
59 //!can't communicate between them.
|
Chris@16
|
60 class windows_shared_memory
|
Chris@16
|
61 {
|
Chris@101
|
62 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
63 //Non-copyable and non-assignable
|
Chris@16
|
64 BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory)
|
Chris@101
|
65 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
66
|
Chris@16
|
67 public:
|
Chris@16
|
68 //!Default constructor.
|
Chris@16
|
69 //!Represents an empty windows_shared_memory.
|
Chris@16
|
70 windows_shared_memory();
|
Chris@16
|
71
|
Chris@101
|
72 //!Creates a new native shared memory with name "name" and at least size "size",
|
Chris@16
|
73 //!with the access mode "mode".
|
Chris@16
|
74 //!If the file previously exists, throws an error.
|
Chris@16
|
75 windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions())
|
Chris@16
|
76 { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); }
|
Chris@16
|
77
|
Chris@101
|
78 //!Tries to create a shared memory object with name "name" and at least size "size", with the
|
Chris@16
|
79 //!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
|
Chris@16
|
80 //!Otherwise throws an error.
|
Chris@16
|
81 windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions())
|
Chris@16
|
82 { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, perm); }
|
Chris@16
|
83
|
Chris@16
|
84 //!Tries to open a shared memory object with name "name", with the access mode "mode".
|
Chris@16
|
85 //!If the file does not previously exist, it throws an error.
|
Chris@16
|
86 windows_shared_memory(open_only_t, const char *name, mode_t mode)
|
Chris@16
|
87 { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); }
|
Chris@16
|
88
|
Chris@16
|
89 //!Moves the ownership of "moved"'s shared memory object to *this.
|
Chris@16
|
90 //!After the call, "moved" does not represent any shared memory object.
|
Chris@16
|
91 //!Does not throw
|
Chris@16
|
92 windows_shared_memory(BOOST_RV_REF(windows_shared_memory) moved)
|
Chris@16
|
93 : m_handle(0)
|
Chris@16
|
94 { this->swap(moved); }
|
Chris@16
|
95
|
Chris@16
|
96 //!Moves the ownership of "moved"'s shared memory to *this.
|
Chris@16
|
97 //!After the call, "moved" does not represent any shared memory.
|
Chris@16
|
98 //!Does not throw
|
Chris@16
|
99 windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved)
|
Chris@16
|
100 {
|
Chris@16
|
101 windows_shared_memory tmp(boost::move(moved));
|
Chris@16
|
102 this->swap(tmp);
|
Chris@16
|
103 return *this;
|
Chris@16
|
104 }
|
Chris@16
|
105
|
Chris@16
|
106 //!Swaps to shared_memory_objects. Does not throw
|
Chris@16
|
107 void swap(windows_shared_memory &other);
|
Chris@16
|
108
|
Chris@16
|
109 //!Destroys *this. All mapped regions are still valid after
|
Chris@16
|
110 //!destruction. When all mapped regions and windows_shared_memory
|
Chris@16
|
111 //!objects referring the shared memory are destroyed, the
|
Chris@16
|
112 //!operating system will destroy the shared memory.
|
Chris@16
|
113 ~windows_shared_memory();
|
Chris@16
|
114
|
Chris@16
|
115 //!Returns the name of the shared memory.
|
Chris@16
|
116 const char *get_name() const;
|
Chris@16
|
117
|
Chris@16
|
118 //!Returns access mode
|
Chris@16
|
119 mode_t get_mode() const;
|
Chris@16
|
120
|
Chris@16
|
121 //!Returns the mapping handle. Never throws
|
Chris@16
|
122 mapping_handle_t get_mapping_handle() const;
|
Chris@16
|
123
|
Chris@101
|
124 //!Returns the size of the windows shared memory. It will be a 4K rounded
|
Chris@101
|
125 //!size of the "size" passed in the constructor.
|
Chris@101
|
126 offset_t get_size() const;
|
Chris@101
|
127
|
Chris@101
|
128 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
129 private:
|
Chris@16
|
130
|
Chris@16
|
131 //!Closes a previously opened file mapping. Never throws.
|
Chris@16
|
132 void priv_close();
|
Chris@16
|
133
|
Chris@16
|
134 //!Closes a previously opened file mapping. Never throws.
|
Chris@16
|
135 bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm = permissions());
|
Chris@16
|
136
|
Chris@16
|
137 void * m_handle;
|
Chris@16
|
138 mode_t m_mode;
|
Chris@16
|
139 std::string m_name;
|
Chris@101
|
140 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
141 };
|
Chris@16
|
142
|
Chris@101
|
143 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
Chris@16
|
144
|
Chris@16
|
145 inline windows_shared_memory::windows_shared_memory()
|
Chris@16
|
146 : m_handle(0)
|
Chris@16
|
147 {}
|
Chris@16
|
148
|
Chris@16
|
149 inline windows_shared_memory::~windows_shared_memory()
|
Chris@16
|
150 { this->priv_close(); }
|
Chris@16
|
151
|
Chris@16
|
152 inline const char *windows_shared_memory::get_name() const
|
Chris@16
|
153 { return m_name.c_str(); }
|
Chris@16
|
154
|
Chris@16
|
155 inline void windows_shared_memory::swap(windows_shared_memory &other)
|
Chris@16
|
156 {
|
Chris@101
|
157 (simple_swap)(m_handle, other.m_handle);
|
Chris@101
|
158 (simple_swap)(m_mode, other.m_mode);
|
Chris@16
|
159 m_name.swap(other.m_name);
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@16
|
162 inline mapping_handle_t windows_shared_memory::get_mapping_handle() const
|
Chris@16
|
163 { mapping_handle_t mhnd = { m_handle, true}; return mhnd; }
|
Chris@16
|
164
|
Chris@16
|
165 inline mode_t windows_shared_memory::get_mode() const
|
Chris@16
|
166 { return m_mode; }
|
Chris@16
|
167
|
Chris@101
|
168 inline offset_t windows_shared_memory::get_size() const
|
Chris@101
|
169 {
|
Chris@101
|
170 offset_t size; //This shall never fail
|
Chris@101
|
171 return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0;
|
Chris@101
|
172 }
|
Chris@101
|
173
|
Chris@16
|
174 inline bool windows_shared_memory::priv_open_or_create
|
Chris@16
|
175 (ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm)
|
Chris@16
|
176 {
|
Chris@16
|
177 m_name = filename ? filename : "";
|
Chris@16
|
178
|
Chris@16
|
179 unsigned long protection = 0;
|
Chris@16
|
180 unsigned long map_access = 0;
|
Chris@16
|
181
|
Chris@16
|
182 switch(mode)
|
Chris@16
|
183 {
|
Chris@16
|
184 //"protection" is for "create_file_mapping"
|
Chris@16
|
185 //"map_access" is for "open_file_mapping"
|
Chris@16
|
186 //Add section query (strange that read or access does not grant it...)
|
Chris@16
|
187 //to obtain the size of the mapping. copy_on_write is equal to section_query.
|
Chris@16
|
188 case read_only:
|
Chris@16
|
189 protection |= winapi::page_readonly;
|
Chris@16
|
190 map_access |= winapi::file_map_read | winapi::section_query;
|
Chris@16
|
191 break;
|
Chris@16
|
192 case read_write:
|
Chris@16
|
193 protection |= winapi::page_readwrite;
|
Chris@16
|
194 map_access |= winapi::file_map_write | winapi::section_query;
|
Chris@16
|
195 break;
|
Chris@16
|
196 case copy_on_write:
|
Chris@16
|
197 protection |= winapi::page_writecopy;
|
Chris@16
|
198 map_access |= winapi::file_map_copy;
|
Chris@16
|
199 break;
|
Chris@16
|
200 default:
|
Chris@16
|
201 {
|
Chris@16
|
202 error_info err(mode_error);
|
Chris@16
|
203 throw interprocess_exception(err);
|
Chris@16
|
204 }
|
Chris@16
|
205 break;
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 switch(type){
|
Chris@16
|
209 case ipcdetail::DoOpen:
|
Chris@16
|
210 m_handle = winapi::open_file_mapping(map_access, filename);
|
Chris@16
|
211 break;
|
Chris@16
|
212 case ipcdetail::DoCreate:
|
Chris@16
|
213 case ipcdetail::DoOpenOrCreate:
|
Chris@16
|
214 {
|
Chris@16
|
215 m_handle = winapi::create_file_mapping
|
Chris@16
|
216 ( winapi::invalid_handle_value, protection, size, filename
|
Chris@16
|
217 , (winapi::interprocess_security_attributes*)perm.get_permissions());
|
Chris@16
|
218 }
|
Chris@16
|
219 break;
|
Chris@16
|
220 default:
|
Chris@16
|
221 {
|
Chris@16
|
222 error_info err = other_error;
|
Chris@16
|
223 throw interprocess_exception(err);
|
Chris@16
|
224 }
|
Chris@16
|
225 }
|
Chris@16
|
226
|
Chris@16
|
227 if(!m_handle || (type == ipcdetail::DoCreate && winapi::get_last_error() == winapi::error_already_exists)){
|
Chris@16
|
228 error_info err = system_error_code();
|
Chris@16
|
229 this->priv_close();
|
Chris@16
|
230 throw interprocess_exception(err);
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233 m_mode = mode;
|
Chris@16
|
234 return true;
|
Chris@16
|
235 }
|
Chris@16
|
236
|
Chris@16
|
237 inline void windows_shared_memory::priv_close()
|
Chris@16
|
238 {
|
Chris@16
|
239 if(m_handle){
|
Chris@16
|
240 winapi::close_handle(m_handle);
|
Chris@16
|
241 m_handle = 0;
|
Chris@16
|
242 }
|
Chris@16
|
243 }
|
Chris@16
|
244
|
Chris@101
|
245 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
Chris@16
|
246
|
Chris@16
|
247 } //namespace interprocess {
|
Chris@16
|
248 } //namespace boost {
|
Chris@16
|
249
|
Chris@16
|
250 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
251
|
Chris@16
|
252 #endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP
|