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.
windows_shared_memory(create_only_t,const char * name,mode_t mode,std::size_t size,const permissions & perm=permissions ())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.
windows_shared_memory(open_or_create_t,const char * name,mode_t mode,std::size_t size,const permissions & perm=permissions ())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.
windows_shared_memory(open_only_t,const char * name,mode_t mode)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
windows_shared_memory(BOOST_RV_REF (windows_shared_memory)moved)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
operator =(BOOST_RV_REF (windows_shared_memory)moved)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 
windows_shared_memory()145 inline windows_shared_memory::windows_shared_memory()
146    :  m_handle(0)
147 {}
148 
~windows_shared_memory()149 inline windows_shared_memory::~windows_shared_memory()
150 {  this->priv_close(); }
151 
get_name() const152 inline const char *windows_shared_memory::get_name() const
153 {  return m_name.c_str(); }
154 
swap(windows_shared_memory & other)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 
get_mapping_handle() const162 inline mapping_handle_t windows_shared_memory::get_mapping_handle() const
163 {  mapping_handle_t mhnd = { m_handle, true};   return mhnd;   }
164 
get_mode() const165 inline mode_t windows_shared_memory::get_mode() const
166 {  return m_mode; }
167 
get_size() const168 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 
priv_open_or_create(ipcdetail::create_enum_t type,const char * filename,mode_t mode,std::size_t size,const permissions & perm)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 
priv_close()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
253