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