Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP Chris@16: #define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@101: Chris@16: #include Chris@101: #include Chris@16: Chris@16: #if !defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: #error "This header can only be used in Windows operating systems" Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: //!\file Chris@16: //!Describes a class representing a native windows shared memory. Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: Chris@16: //!A class that wraps the native Windows shared memory Chris@16: //!that is implemented as a file mapping of the paging file. Chris@16: //!Unlike shared_memory_object, windows_shared_memory has Chris@16: //!no kernel persistence and the shared memory is destroyed Chris@16: //!when all processes destroy all their windows_shared_memory Chris@16: //!objects and mapped regions for the same shared memory Chris@16: //!or the processes end/crash. Chris@16: //! Chris@16: //!Warning: Windows native shared memory and interprocess portable Chris@16: //!shared memory (boost::interprocess::shared_memory_object) Chris@16: //!can't communicate between them. Chris@16: class windows_shared_memory Chris@16: { Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: //Non-copyable and non-assignable Chris@16: BOOST_MOVABLE_BUT_NOT_COPYABLE(windows_shared_memory) Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: //!Default constructor. Chris@16: //!Represents an empty windows_shared_memory. Chris@16: windows_shared_memory(); Chris@16: Chris@101: //!Creates a new native shared memory with name "name" and at least size "size", Chris@16: //!with the access mode "mode". Chris@16: //!If the file previously exists, throws an error. Chris@16: windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) Chris@16: { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } Chris@16: Chris@101: //!Tries to create a shared memory object with name "name" and at least size "size", with the Chris@16: //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". Chris@16: //!Otherwise throws an error. Chris@16: windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) Chris@16: { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, perm); } Chris@16: Chris@16: //!Tries to open a shared memory object with name "name", with the access mode "mode". Chris@16: //!If the file does not previously exist, it throws an error. Chris@16: windows_shared_memory(open_only_t, const char *name, mode_t mode) Chris@16: { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } Chris@16: Chris@16: //!Moves the ownership of "moved"'s shared memory object to *this. Chris@16: //!After the call, "moved" does not represent any shared memory object. Chris@16: //!Does not throw Chris@16: windows_shared_memory(BOOST_RV_REF(windows_shared_memory) moved) Chris@16: : m_handle(0) Chris@16: { this->swap(moved); } Chris@16: Chris@16: //!Moves the ownership of "moved"'s shared memory to *this. Chris@16: //!After the call, "moved" does not represent any shared memory. Chris@16: //!Does not throw Chris@16: windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved) Chris@16: { Chris@16: windows_shared_memory tmp(boost::move(moved)); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //!Swaps to shared_memory_objects. Does not throw Chris@16: void swap(windows_shared_memory &other); Chris@16: Chris@16: //!Destroys *this. All mapped regions are still valid after Chris@16: //!destruction. When all mapped regions and windows_shared_memory Chris@16: //!objects referring the shared memory are destroyed, the Chris@16: //!operating system will destroy the shared memory. Chris@16: ~windows_shared_memory(); Chris@16: Chris@16: //!Returns the name of the shared memory. Chris@16: const char *get_name() const; Chris@16: Chris@16: //!Returns access mode Chris@16: mode_t get_mode() const; Chris@16: Chris@16: //!Returns the mapping handle. Never throws Chris@16: mapping_handle_t get_mapping_handle() const; Chris@16: Chris@101: //!Returns the size of the windows shared memory. It will be a 4K rounded Chris@101: //!size of the "size" passed in the constructor. Chris@101: offset_t get_size() const; Chris@101: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: Chris@16: //!Closes a previously opened file mapping. Never throws. Chris@16: void priv_close(); Chris@16: Chris@16: //!Closes a previously opened file mapping. Never throws. Chris@16: 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: Chris@16: void * m_handle; Chris@16: mode_t m_mode; Chris@16: std::string m_name; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: Chris@16: inline windows_shared_memory::windows_shared_memory() Chris@16: : m_handle(0) Chris@16: {} Chris@16: Chris@16: inline windows_shared_memory::~windows_shared_memory() Chris@16: { this->priv_close(); } Chris@16: Chris@16: inline const char *windows_shared_memory::get_name() const Chris@16: { return m_name.c_str(); } Chris@16: Chris@16: inline void windows_shared_memory::swap(windows_shared_memory &other) Chris@16: { Chris@101: (simple_swap)(m_handle, other.m_handle); Chris@101: (simple_swap)(m_mode, other.m_mode); Chris@16: m_name.swap(other.m_name); Chris@16: } Chris@16: Chris@16: inline mapping_handle_t windows_shared_memory::get_mapping_handle() const Chris@16: { mapping_handle_t mhnd = { m_handle, true}; return mhnd; } Chris@16: Chris@16: inline mode_t windows_shared_memory::get_mode() const Chris@16: { return m_mode; } Chris@16: Chris@101: inline offset_t windows_shared_memory::get_size() const Chris@101: { Chris@101: offset_t size; //This shall never fail Chris@101: return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0; Chris@101: } Chris@101: Chris@16: inline bool windows_shared_memory::priv_open_or_create Chris@16: (ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm) Chris@16: { Chris@16: m_name = filename ? filename : ""; Chris@16: Chris@16: unsigned long protection = 0; Chris@16: unsigned long map_access = 0; Chris@16: Chris@16: switch(mode) Chris@16: { Chris@16: //"protection" is for "create_file_mapping" Chris@16: //"map_access" is for "open_file_mapping" Chris@16: //Add section query (strange that read or access does not grant it...) Chris@16: //to obtain the size of the mapping. copy_on_write is equal to section_query. Chris@16: case read_only: Chris@16: protection |= winapi::page_readonly; Chris@16: map_access |= winapi::file_map_read | winapi::section_query; Chris@16: break; Chris@16: case read_write: Chris@16: protection |= winapi::page_readwrite; Chris@16: map_access |= winapi::file_map_write | winapi::section_query; Chris@16: break; Chris@16: case copy_on_write: Chris@16: protection |= winapi::page_writecopy; Chris@16: map_access |= winapi::file_map_copy; Chris@16: break; Chris@16: default: Chris@16: { Chris@16: error_info err(mode_error); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: break; Chris@16: } Chris@16: Chris@16: switch(type){ Chris@16: case ipcdetail::DoOpen: Chris@16: m_handle = winapi::open_file_mapping(map_access, filename); Chris@16: break; Chris@16: case ipcdetail::DoCreate: Chris@16: case ipcdetail::DoOpenOrCreate: Chris@16: { Chris@16: m_handle = winapi::create_file_mapping Chris@16: ( winapi::invalid_handle_value, protection, size, filename Chris@16: , (winapi::interprocess_security_attributes*)perm.get_permissions()); Chris@16: } Chris@16: break; Chris@16: default: Chris@16: { Chris@16: error_info err = other_error; Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: if(!m_handle || (type == ipcdetail::DoCreate && winapi::get_last_error() == winapi::error_already_exists)){ Chris@16: error_info err = system_error_code(); Chris@16: this->priv_close(); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: Chris@16: m_mode = mode; Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline void windows_shared_memory::priv_close() Chris@16: { Chris@16: if(m_handle){ Chris@16: winapi::close_handle(m_handle); Chris@16: m_handle = 0; Chris@16: } Chris@16: } Chris@16: Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: } //namespace interprocess { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP