From a86d42120edcaf024db36c38cf0578280b3714ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 26 Dec 2010 09:47:54 +0000 Subject: [PATCH] Added XSI shared memory [SVN r67449] --- .../containers/containers_fwd.hpp | 2 + .../interprocess/detail/file_wrapper.hpp | 1 + .../detail/managed_open_or_create_impl.hpp | 116 ++++++++--- .../interprocess/detail/os_file_functions.hpp | 29 ++- .../boost/interprocess/detail/win32_api.hpp | 105 +++++----- .../detail/xsi_shared_memory_device.hpp | 11 +- .../detail/xsi_shared_memory_file_wrapper.hpp | 80 ++++++++ .../boost/interprocess/interprocess_fwd.hpp | 12 +- .../managed_xsi_shared_memory.hpp | 189 ++++++++++++++++++ include/boost/interprocess/permissions.hpp | 25 ++- .../interprocess/shared_memory_object.hpp | 43 ++-- include/boost/interprocess/xsi_key.hpp | 87 ++++++++ .../{detail => }/xsi_shared_memory.hpp | 79 +++----- 13 files changed, 612 insertions(+), 167 deletions(-) create mode 100644 include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp create mode 100644 include/boost/interprocess/managed_xsi_shared_memory.hpp create mode 100644 include/boost/interprocess/xsi_key.hpp rename include/boost/interprocess/{detail => }/xsi_shared_memory.hpp (67%) diff --git a/include/boost/interprocess/containers/containers_fwd.hpp b/include/boost/interprocess/containers/containers_fwd.hpp index fb7d4ab..9afa848 100644 --- a/include/boost/interprocess/containers/containers_fwd.hpp +++ b/include/boost/interprocess/containers/containers_fwd.hpp @@ -35,4 +35,6 @@ using boost::container::ordered_unique_range; #include +/// @endcond + #endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP diff --git a/include/boost/interprocess/detail/file_wrapper.hpp b/include/boost/interprocess/detail/file_wrapper.hpp index 1196bb0..10d9f62 100644 --- a/include/boost/interprocess/detail/file_wrapper.hpp +++ b/include/boost/interprocess/detail/file_wrapper.hpp @@ -53,6 +53,7 @@ class file_wrapper //!After the call, "moved" does not represent any file. //!Does not throw file_wrapper(BOOST_INTERPROCESS_RV_REF(file_wrapper) moved) + : m_handle(file_handle_t(detail::invalid_file())) { this->swap(moved); } //!Moves the ownership of "moved"'s file to *this. diff --git a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp index b3e885a..24a8a48 100644 --- a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -30,16 +30,66 @@ namespace interprocess { /// @cond namespace detail{ class interprocess_tester; } + + +template +struct managed_open_or_create_impl_device_id_t +{ + typedef const char *type; +}; + +#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + +class xsi_shared_memory_file_wrapper; +class xsi_key; + +template<> +struct managed_open_or_create_impl_device_id_t +{ + typedef xsi_key type; +}; + +#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + /// @endcond namespace detail { -template + +template +class managed_open_or_create_impl_device_holder +{ + public: + DeviceAbstraction &get_device() + { static DeviceAbstraction dev; return dev; } + + const DeviceAbstraction &get_device() const + { static DeviceAbstraction dev; return dev; } +}; + +template +class managed_open_or_create_impl_device_holder +{ + public: + DeviceAbstraction &get_device() + { return dev; } + + const DeviceAbstraction &get_device() const + { return dev; } + + private: + DeviceAbstraction dev; +}; + +template class managed_open_or_create_impl + : public managed_open_or_create_impl_device_holder { //Non-copyable BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl) + typedef typename managed_open_or_create_impl_device_id_t::type device_id_t; + typedef managed_open_or_create_impl_device_holder DevHolder; enum { UninitializedSegment, @@ -59,15 +109,15 @@ class managed_open_or_create_impl {} managed_open_or_create_impl(create_only_t, - const char *name, + const device_id_t & id, std::size_t size, mode_t mode, const void *addr, const permissions &perm) { - m_name = name; priv_open_or_create ( detail::DoCreate + , id , size , mode , addr @@ -76,13 +126,13 @@ class managed_open_or_create_impl } managed_open_or_create_impl(open_only_t, - const char *name, + const device_id_t & id, mode_t mode, const void *addr) { - m_name = name; priv_open_or_create ( detail::DoOpen + , id , 0 , mode , addr @@ -92,15 +142,15 @@ class managed_open_or_create_impl managed_open_or_create_impl(open_or_create_t, - const char *name, + const device_id_t & id, std::size_t size, mode_t mode, const void *addr, const permissions &perm) { - m_name = name; priv_open_or_create ( detail::DoOpenOrCreate + , id , size , mode , addr @@ -110,16 +160,16 @@ class managed_open_or_create_impl template managed_open_or_create_impl(create_only_t, - const char *name, + const device_id_t & id, std::size_t size, mode_t mode, const void *addr, const ConstructFunc &construct_func, const permissions &perm) { - m_name = name; priv_open_or_create (detail::DoCreate + , id , size , mode , addr @@ -129,14 +179,14 @@ class managed_open_or_create_impl template managed_open_or_create_impl(open_only_t, - const char *name, + const device_id_t & id, mode_t mode, const void *addr, const ConstructFunc &construct_func) { - m_name = name; priv_open_or_create ( detail::DoOpen + , id , 0 , mode , addr @@ -146,16 +196,16 @@ class managed_open_or_create_impl template managed_open_or_create_impl(open_or_create_t, - const char *name, + const device_id_t & id, std::size_t size, mode_t mode, const void *addr, const ConstructFunc &construct_func, const permissions &perm) { - m_name = name; priv_open_or_create ( detail::DoOpenOrCreate + , id , size , mode , addr @@ -190,20 +240,22 @@ class managed_open_or_create_impl void swap(managed_open_or_create_impl &other) { - this->m_name.swap(other.m_name); this->m_mapped_region.swap(other.m_mapped_region); } - const char *get_name() const - { return m_name.c_str(); } - bool flush() { return m_mapped_region.flush(); } - const mapped_region &get_mapped_region() const { return m_mapped_region; } + + DeviceAbstraction &get_device() + { return this->DevHolder::get_device(); } + + const DeviceAbstraction &get_device() const + { return this->DevHolder::get_device(); } + private: //These are templatized to allow explicit instantiations @@ -217,22 +269,24 @@ class managed_open_or_create_impl //These are templatized to allow explicit instantiations template - static void create_device(DeviceAbstraction &dev, const char *name, std::size_t size, const permissions &perm, detail::false_) + static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, detail::false_) { - DeviceAbstraction tmp(create_only, name, read_write, size, perm); + DeviceAbstraction tmp(create_only, id, read_write, size, perm); tmp.swap(dev); } template - static void create_device(DeviceAbstraction &dev, const char *name, std::size_t, const permissions &perm, detail::true_) + static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, detail::true_) { - DeviceAbstraction tmp(create_only, name, read_write, perm); + DeviceAbstraction tmp(create_only, id, read_write, perm); tmp.swap(dev); } template inline void priv_open_or_create - (detail::create_enum_t type, std::size_t size, + (detail::create_enum_t type, + const device_id_t & id, + std::size_t size, mode_t mode, const void *addr, const permissions &perm, ConstructFunc construct_func) @@ -250,24 +304,24 @@ class managed_open_or_create_impl } if(type == detail::DoOpen && mode == read_write){ - DeviceAbstraction tmp(open_only, m_name.c_str(), read_write); + DeviceAbstraction tmp(open_only, id, read_write); tmp.swap(dev); created = false; } else if(type == detail::DoOpen && mode == read_only){ - DeviceAbstraction tmp(open_only, m_name.c_str(), read_only); + DeviceAbstraction tmp(open_only, id, read_only); tmp.swap(dev); created = false; ronly = true; } else if(type == detail::DoOpen && mode == copy_on_write){ - DeviceAbstraction tmp(open_only, m_name.c_str(), read_only); + DeviceAbstraction tmp(open_only, id, read_only); tmp.swap(dev); created = false; cow = true; } else if(type == detail::DoCreate){ - create_device(dev, m_name.c_str(), size, perm, file_like_t()); + create_device(dev, id, size, perm, file_like_t()); created = true; } else if(type == detail::DoOpenOrCreate){ @@ -278,7 +332,7 @@ class managed_open_or_create_impl bool completed = false; while(!completed){ try{ - create_device(dev, m_name.c_str(), size, perm, file_like_t()); + create_device(dev, id, size, perm, file_like_t()); created = true; completed = true; } @@ -288,7 +342,7 @@ class managed_open_or_create_impl } else{ try{ - DeviceAbstraction tmp(open_only, m_name.c_str(), read_write); + DeviceAbstraction tmp(open_only, id, read_write); dev.swap(tmp); created = false; completed = true; @@ -376,6 +430,9 @@ class managed_open_or_create_impl //All ok, just move resources to the external mapped region m_mapped_region.swap(region); } + if(StoreDevice){ + this->DevHolder::get_device() = boost::interprocess::move(dev); + } } private: @@ -384,7 +441,6 @@ class managed_open_or_create_impl { detail::interprocess_tester::dont_close_on_destruction(m_mapped_region); } mapped_region m_mapped_region; - std::string m_name; }; template diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index 3c1b99b..3cc9755 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -93,7 +93,7 @@ inline const char *get_temporary_path() inline file_handle_t create_new_file - (const char *name, mode_t mode, const permissions & perm, bool temporary = false) + (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) { unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file @@ -102,7 +102,7 @@ inline file_handle_t create_new_file } inline file_handle_t create_or_open_file - (const char *name, mode_t mode, const permissions & perm, bool temporary = false) + (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) { unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file @@ -395,7 +395,7 @@ inline const char *get_temporary_path() } inline file_handle_t create_new_file - (const char *name, mode_t mode, const permissions & perm, bool temporary = false) + (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) { (void)temporary; int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); @@ -406,12 +406,23 @@ inline file_handle_t create_new_file } inline file_handle_t create_or_open_file - (const char *name, mode_t mode, const permissions & perm, bool temporary = false) -{ + (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) +{ (void)temporary; - int ret = ::open(name, ((int)mode) | O_CREAT, perm.get_permissions()); - if(ret >= 0){ - ::fchmod(ret, perm.get_permissions()); + int ret = -1; + //We need a loop to change permissions correctly using fchmod, since + //with "O_CREAT only" ::open we don't know if we've created or opened the file. + while(1){ + ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); + if(ret >= 0){ + ::fchmod(ret, perm.get_permissions()); + break; + } + else if(errno == EEXIST){ + if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){ + break; + } + } } return ret; } @@ -420,7 +431,7 @@ inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) { (void)temporary; - return ::open(name, (int)mode, 0666); + return ::open(name, (int)mode); } inline bool delete_file(const char *name) diff --git a/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index cdcb00e..6a4f1b7 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -154,6 +154,7 @@ static const long BootAndSystemstampLength = 16; static const long BootstampLength = 8; static const unsigned long MaxPath = 260; + //Keys static void * const hkey_local_machine = (void*)(unsigned long*)(long)(0x80000002); static unsigned long key_query_value = 0x0001; @@ -165,7 +166,10 @@ const long EOAC_NONE_IG = 0; const long CLSCTX_INPROC_SERVER_IG = 0x1; const long CLSCTX_LOCAL_SERVER_IG = 0x4; const long WBEM_FLAG_RETURN_IMMEDIATELY_IG = 0x10; -const long WBEM_INFINITE_IG = 0xffffffff; +const long WBEM_INFINITE_IG = 0xffffffffL; +const long RPC_E_TOO_LATE_IG = 0x80010119L; +const long S_OK_IG = 0L; +const long S_FALSE_IG = 1; } //namespace winapi { } //namespace interprocess { @@ -1448,33 +1452,54 @@ inline void get_registry_value(const char *folder, const char *value_key, std::v } } +struct co_uninitializer +{ ~co_uninitializer() { CoUninitialize(); } }; + +template +struct com_releaser +{ + Object *&object_; + com_releaser(Object *&object) : object_(object) {} + ~com_releaser() { object_->Release(); object_ = 0; } +}; + inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var) { - CoInitialize(0); - + //See example http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx + long co_init_ret = CoInitialize(0); + if(co_init_ret != S_OK_IG && co_init_ret != S_FALSE_IG) + return false; + co_uninitializer co_initialize_end; + bool bRet = false; - - if( 0 == CoInitializeSecurity( 0, -1, 0, 0, RPC_C_AUTHN_LEVEL_PKT_IG, RPC_C_IMP_LEVEL_IMPERSONATE_IG, 0, EOAC_NONE_IG, 0 ) ) + long sec_init_ret = CoInitializeSecurity + ( 0 //pVoid + ,-1 //cAuthSvc + , 0 //asAuthSvc + , 0 //pReserved1 + , RPC_C_AUTHN_LEVEL_PKT_IG //dwAuthnLevel + , RPC_C_IMP_LEVEL_IMPERSONATE_IG //dwImpLevel + , 0 //pAuthList + , EOAC_NONE_IG //dwCapabilities + , 0 //pReserved3 + ); + if( 0 == sec_init_ret || RPC_E_TOO_LATE_IG == sec_init_ret) { IWbemLocator_IG * pIWbemLocator = 0; - - IWbemServices_IG * pWbemServices = 0; - IEnumWbemClassObject_IG * pEnumObject = 0; - const wchar_t * bstrNamespace = L"root\\cimv2"; if( 0 != CoCreateInstance( CLSID_WbemAdministrativeLocator, 0, CLSCTX_INPROC_SERVER_IG | CLSCTX_LOCAL_SERVER_IG, - IID_IUnknown, - ( void ** )&pIWbemLocator - ) - ) - { + IID_IUnknown, (void **)&pIWbemLocator)){ return false; } + com_releaser IWbemLocator_releaser(pIWbemLocator); + + IWbemServices_IG *pWbemServices = 0; + if( 0 != pIWbemLocator->ConnectServer( bstrNamespace, // Namespace 0, // Userid @@ -1485,19 +1510,20 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ 0, // Context &pWbemServices ) - ) - { - pIWbemLocator->Release(); - + ){ return false; } - + + com_releaser IWbemServices_releaser(pWbemServices); + strValue.clear(); strValue += L"Select "; strValue += wmi_class_var; strValue += L" from "; strValue += wmi_class; + IEnumWbemClassObject_IG * pEnumObject = 0; + if ( 0 != pWbemServices->ExecQuery( L"WQL", strValue.c_str(), @@ -1505,47 +1531,30 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ 0, &pEnumObject ) - ) - { - pIWbemLocator->Release(); - pWbemServices->Release(); - + ){ return false; } - - unsigned long uCount = 1, uReturned; - IWbemClassObject_IG * pClassObject = 0; - - if ( 0 != pEnumObject->Reset() ) - { - pIWbemLocator->Release(); - pWbemServices->Release(); - pEnumObject->Release(); - + + com_releaser IEnumWbemClassObject_releaser(pEnumObject); + + if ( 0 != pEnumObject->Reset() ){ return false; } wchar_variant vwchar; - + unsigned long uCount = 1, uReturned; + IWbemClassObject_IG * pClassObject = 0; while( 0 == pEnumObject->Next( WBEM_INFINITE_IG, uCount, &pClassObject, &uReturned ) ) { - if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) ) - { + com_releaser IWbemClassObject_releaser(pClassObject); + if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){ bRet = true; - strValue = vwchar.value.pbstrVal; - VariantClear(&vwchar ); - break; + strValue = vwchar.value.pbstrVal; + VariantClear(&vwchar ); + break; } } - - pIWbemLocator->Release(); - pWbemServices->Release(); - pEnumObject->Release(); - pClassObject->Release(); } - - CoUninitialize(); - return bRet; } diff --git a/include/boost/interprocess/detail/xsi_shared_memory_device.hpp b/include/boost/interprocess/detail/xsi_shared_memory_device.hpp index b2014c4..59ec2ca 100644 --- a/include/boost/interprocess/detail/xsi_shared_memory_device.hpp +++ b/include/boost/interprocess/detail/xsi_shared_memory_device.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2010. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -45,13 +45,10 @@ namespace interprocess { class xsi_shared_memory_device { /// @cond - //Non-copyable and non-assignable - xsi_shared_memory_device(xsi_shared_memory_device &); - xsi_shared_memory_device &operator=(xsi_shared_memory_device &); - /// @endcond + BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) + /// @endcond public: - BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(xsi_shared_memory_device) xsi_shared_memory_device(); diff --git a/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp new file mode 100644 index 0000000..d09ca37 --- /dev/null +++ b/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2010. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP +#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP + +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +//!\file +//!Describes a class representing a pseudo-file implemented on top of xsi shared memory. + +namespace boost { +namespace interprocess { + +class xsi_shared_memory_file_wrapper + : public xsi_shared_memory +{ + /// @cond + BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) + /// @endcond + public: + + xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} + + xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions()) + {} + + xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions()) + {} + + xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions()) + : xsi_shared_memory(open_only_t(), key) + {} + + xsi_shared_memory_file_wrapper(BOOST_INTERPROCESS_RV_REF(xsi_shared_memory_file_wrapper) moved) + { this->swap(moved); } + + xsi_shared_memory_file_wrapper &operator=(BOOST_INTERPROCESS_RV_REF(xsi_shared_memory_file_wrapper) moved) + { + xsi_shared_memory_file_wrapper tmp(boost::interprocess::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps two xsi_shared_memory_file_wrapper. Does not throw + void swap(xsi_shared_memory_file_wrapper &other) + { this->xsi_shared_memory::swap(other); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP diff --git a/include/boost/interprocess/interprocess_fwd.hpp b/include/boost/interprocess/interprocess_fwd.hpp index 917f750..0d8d44e 100644 --- a/include/boost/interprocess/interprocess_fwd.hpp +++ b/include/boost/interprocess/interprocess_fwd.hpp @@ -67,7 +67,7 @@ class permissions; class shared_memory_object; -#if defined (BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) class windows_shared_memory; #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) @@ -239,7 +239,7 @@ wmanaged_shared_memory; // Windows shared memory managed memory classes ////////////////////////////////////////////////////////////////////////////// -#if defined (BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template wmanaged_windows_shared_memory; -#else +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) + +#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) template class IndexType> @@ -277,9 +278,8 @@ typedef basic_managed_xsi_shared_memory ,rbtree_best_fit ,iset_index> wmanaged_xsi_shared_memory; -#endif //#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) -#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) ////////////////////////////////////////////////////////////////////////////// // Fixed address shared memory diff --git a/include/boost/interprocess/managed_xsi_shared_memory.hpp b/include/boost/interprocess/managed_xsi_shared_memory.hpp new file mode 100644 index 0000000..9ff7f7f --- /dev/null +++ b/include/boost/interprocess/managed_xsi_shared_memory.hpp @@ -0,0 +1,189 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include + +namespace boost { + +namespace interprocess { + +//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_xsi_shared_memory + : public detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> + , private detail::managed_open_or_create_impl +{ + /// @cond + public: + typedef xsi_shared_memory_file_wrapper device_type; + + public: + typedef detail::managed_open_or_create_impl + base2_t; + typedef detail::basic_managed_memory_impl + base_t; + + typedef detail::create_open_func create_open_func_t; + + basic_managed_xsi_shared_memory *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory) + /// @endcond + + public: //functions + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_xsi_shared_memory() + {} + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_xsi_shared_memory() + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_xsi_shared_memory(create_only_t create_only, const xsi_key &key, + std::size_t size, const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(create_only, key, size, read_write, addr, + create_open_func_t(get_this_pointer(), detail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_xsi_shared_memory (open_or_create_t open_or_create, + const xsi_key &key, std::size_t size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, key, size, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key, + const void *addr = 0) + : base_t() + , base2_t(open_only, key, read_only, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key, + const void *addr = 0) + : base_t() + , base2_t(open_only, key, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_xsi_shared_memory(BOOST_INTERPROCESS_RV_REF(basic_managed_xsi_shared_memory) moved) + { + basic_managed_xsi_shared_memory tmp; + this->swap(moved); + tmp.swap(moved); + } + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + basic_managed_xsi_shared_memory &operator=(BOOST_INTERPROCESS_RV_REF(basic_managed_xsi_shared_memory) moved) + { + basic_managed_xsi_shared_memory tmp(boost::interprocess::move(moved)); + this->swap(tmp); + return *this; + } + + //!Swaps the ownership of the managed shared memories managed by *this and other. + //!Never throws. + void swap(basic_managed_xsi_shared_memory &other) + { + base_t::swap(other); + base2_t::swap(other); + } + + //!Erases a XSI shared memory object identified by shmid + //!from the system. + //!Returns false on error. Never throws + static bool remove(int shmid) + { return device_type::remove(shmid); } + + int get_shmid() const + { return base2_t::get_device().get_shmid(); } + + /// @cond + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(base2_t::get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + /// @endcond +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP + diff --git a/include/boost/interprocess/permissions.hpp b/include/boost/interprocess/permissions.hpp index aa88d61..4db45b8 100644 --- a/include/boost/interprocess/permissions.hpp +++ b/include/boost/interprocess/permissions.hpp @@ -11,7 +11,9 @@ #ifndef BOOST_INTERPROCESS_PERMISSIONS_HPP #define BOOST_INTERPROCESS_PERMISSIONS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +/// @cond + +#if defined (_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif @@ -25,12 +27,16 @@ #endif +/// @endcond + //!\file //!Describes permissions class namespace boost { namespace interprocess { +/// @cond + #if defined(BOOST_INTERPROCESS_WINDOWS) namespace detail { @@ -48,18 +54,22 @@ winapi::interprocess_all_access_security unrestricted_permissions_holder: #endif //defined BOOST_INTERPROCESS_WINDOWS +/// @endcond + //!The permissions class represents permissions to be set to shared memory or //!files, that can be constructed form usual permission representations: //!a SECURITY_ATTRIBUTES pointer in windows or ORed rwx chmod integer in UNIX. class permissions { /// @cond - #if defined (BOOST_INTERPROCESS_WINDOWS) + + #if defined(BOOST_INTERPROCESS_WINDOWS) typedef void* os_permissions_type; #else typedef int os_permissions_type; - #endif //#if (defined BOOST_INTERPROCESS_WINDOWS) + #endif os_permissions_type m_perm; + /// @endcond public: @@ -80,22 +90,26 @@ class permissions //!for UNIX. void set_default() { - #if (defined BOOST_INTERPROCESS_WINDOWS) + /// @cond + #if defined (BOOST_INTERPROCESS_WINDOWS) m_perm = 0; #else m_perm = 0644; #endif + /// @endcond } //!Sets permissions to unrestricted access: //!A null DACL for windows or 0666 for UNIX. void set_unrestricted() { - #if (defined BOOST_INTERPROCESS_WINDOWS) + /// @cond + #if defined (BOOST_INTERPROCESS_WINDOWS) m_perm = &detail::unrestricted_permissions_holder<0>::unrestricted; #else m_perm = 0666; #endif + /// @endcond } //!Sets permissions from a user provided os-dependent @@ -115,3 +129,4 @@ class permissions #include #endif //BOOST_INTERPROCESS_PERMISSIONS_HPP + diff --git a/include/boost/interprocess/shared_memory_object.hpp b/include/boost/interprocess/shared_memory_object.hpp index b7560e3..98fa5c4 100644 --- a/include/boost/interprocess/shared_memory_object.hpp +++ b/include/boost/interprocess/shared_memory_object.hpp @@ -298,29 +298,48 @@ inline bool shared_memory_object::priv_open_or_create error_info err(mode_error); throw interprocess_exception(err); } + int unix_perm = perm.get_permissions(); switch(type){ case detail::DoOpen: - //No addition + { + //No oflag addition + m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + } break; case detail::DoCreate: + { oflag |= (O_CREAT | O_EXCL); + m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + if(m_handle >= 0){ + ::fchmod(m_handle, unix_perm); + } + } break; case detail::DoOpenOrCreate: + { oflag |= O_CREAT; + //We need a loop to change permissions correctly using fchmod, since + //with "O_CREAT only" shm_open we don't know if we've created or opened the file. + while(1){ + m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + if(m_handle >= 0){ + ::fchmod(m_handle, unix_perm); + break; + } + else if(errno == EEXIST){ + if((m_handle = shm_open(m_filename.c_str(), oflag, unix_perm)) >= 0 || errno != ENOENT){ + break; + } + } + } + } break; default: - { - error_info err = other_error; - throw interprocess_exception(err); - } - } - - //Open file using POSIX API - m_handle = shm_open(m_filename.c_str(), oflag, perm.get_permissions()); - - if(m_handle >= 0){ - ::fchmod(m_handle, perm.get_permissions()); + { + error_info err = other_error; + throw interprocess_exception(err); + } } //Check for error diff --git a/include/boost/interprocess/xsi_key.hpp b/include/boost/interprocess/xsi_key.hpp new file mode 100644 index 0000000..addeff9 --- /dev/null +++ b/include/boost/interprocess/xsi_key.hpp @@ -0,0 +1,87 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_XSI_KEY_HPP +#define BOOST_INTERPROCESS_XSI_KEY_HPP + +#include +#include +#include + +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a class representing a xsi key type. + +namespace boost { +namespace interprocess { + +//!A class that wraps XSI (System V) key_t type. +//!This type calculates key_t from path and id using ftok +//!or sets key to IPC_PRIVATE using the default constructor. +class xsi_key +{ + public: + + //!Default constructor. + //!Represents a private xsi_key. + xsi_key() + : m_key(IPC_PRIVATE) + {} + + //!Creates a new XSI shared memory with a key obtained from a call to ftok (with path + //!"path" and id "id"), of size "size" and permissions "perm". + //!If the shared memory previously exists, throws an error. + xsi_key(const char *path, boost::uint8_t id) + { + key_t key; + if(path){ + key = ::ftok(path, id); + if(((key_t)-1) == key){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + else{ + key = IPC_PRIVATE; + } + m_key = key; + } + + //!Returns the internal key_t value + key_t get_key() const + { return m_key; } + + /// @cond + private: + key_t m_key; + /// @endcond +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_XSI_KEY_HPP diff --git a/include/boost/interprocess/detail/xsi_shared_memory.hpp b/include/boost/interprocess/xsi_shared_memory.hpp similarity index 67% rename from include/boost/interprocess/detail/xsi_shared_memory.hpp rename to include/boost/interprocess/xsi_shared_memory.hpp index 297e9a5..1d248d6 100644 --- a/include/boost/interprocess/detail/xsi_shared_memory.hpp +++ b/include/boost/interprocess/xsi_shared_memory.hpp @@ -15,20 +15,22 @@ #include #include -#if defined(BOOST_INTERPROCESS_WINDOWS) -#error "This header can't be used in Windows operating systems" +#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) +#error "This header can't be used in operating systems without XSI (System V) shared memory support" #endif #include #include #include +#include #include #include #include +#include +#include #include #include #include -#include //!\file //!Describes a class representing a native xsi shared memory. @@ -38,10 +40,7 @@ namespace interprocess { //!A class that wraps XSI (System V) shared memory. //!Unlike shared_memory_object, xsi_shared_memory needs a valid -//!path and a 8 bit key to identify a shared memory create -//!when all processes destroy all their xsi_shared_memory -//!objects and mapped regions for the same shared memory -//!or the processes end/crash. +//!xsi_key to identify a shared memory object. //! //!Warning: XSI shared memory and interprocess portable //!shared memory (boost::interprocess::shared_memory_object) @@ -50,40 +49,40 @@ class xsi_shared_memory { /// @cond //Non-copyable and non-assignable - xsi_shared_memory(xsi_shared_memory &); - xsi_shared_memory &operator=(xsi_shared_memory &); + BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory) /// @endcond public: - BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(xsi_shared_memory) - //!Default constructor. //!Represents an empty xsi_shared_memory. xsi_shared_memory(); - //!Creates a new XSI shared memory with a key obtained from a call to ftok (with path - //!"path" and id "id"), of size "size" and permissions "perm". + //!Initializes *this with a shmid previously obtained (possibly from another process) + //!This lower-level initializer allows shared memory mapping without having a key. + xsi_shared_memory(open_only_t, int shmid) + : m_shmid (shmid) + {} + + //!Creates a new XSI shared memory from 'key', with size "size" and permissions "perm". //!If the shared memory previously exists, throws an error. - xsi_shared_memory(create_only_t, const char *path, boost::uint8_t id, std::size_t size, int perm = 0666) - { this->priv_open_or_create(detail::DoCreate, path, id, perm, size); } + xsi_shared_memory(create_only_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(detail::DoCreate, key, perm, size); } - //!Tries to create a new XSI shared memory with a key obtained from a call to ftok (with path - //!"path" and id "id"), of size "size" and permissions "perm". - //!If the shared memory previously exists, it tries to open it. - //!Otherwise throws an error. - xsi_shared_memory(open_or_create_t, const char *path, boost::uint8_t id, std::size_t size, int perm = 0666) - { this->priv_open_or_create(detail::DoOpenOrCreate, path, id, perm, size); } + //!Opens an existing shared memory with identifier 'key' or creates a new XSI shared memory from + //!identifier 'key', with size "size" and permissions "perm". + xsi_shared_memory(open_or_create_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(detail::DoOpenOrCreate, key, perm, size); } - //!Tries to open a XSI shared memory with a key obtained from a call to ftok (with path - //!"path" and id "id") and permissions "perm". + //!Tries to open a XSI shared memory with identifier 'key' //!If the shared memory does not previously exist, it throws an error. - xsi_shared_memory(open_only_t, const char *path, boost::uint8_t id, int perm = 0666) - { this->priv_open_or_create(detail::DoOpen, path, id, perm, 0); } + xsi_shared_memory(open_only_t, const xsi_key &key) + { this->priv_open_or_create(detail::DoOpen, key, permissions(), 0); } //!Moves the ownership of "moved"'s shared memory object to *this. //!After the call, "moved" does not represent any shared memory object. //!Does not throw xsi_shared_memory(BOOST_INTERPROCESS_RV_REF(xsi_shared_memory) moved) + : m_shmid(-1) { this->swap(moved); } //!Moves the ownership of "moved"'s shared memory to *this. @@ -103,18 +102,10 @@ class xsi_shared_memory //!this connection to it. Use remove() to destroy the shared memory. ~xsi_shared_memory(); - //!Returns the path used to - //!obtain the key. - const char *get_path() const; - //!Returns the shared memory ID that //!identifies the shared memory int get_shmid() const; - //!Returns access - //!permissions - int get_permissions() const; - //!Returns the mapping handle. //!Never throws mapping_handle_t get_mapping_handle() const; @@ -129,9 +120,8 @@ class xsi_shared_memory //!Closes a previously opened file mapping. Never throws. bool priv_open_or_create( detail::create_enum_t type - , const char *filename - , boost::uint8_t id - , int perm + , const xsi_key &key + , const permissions& perm , std::size_t size); int m_shmid; /// @endcond @@ -158,20 +148,9 @@ inline mapping_handle_t xsi_shared_memory::get_mapping_handle() const { mapping_handle_t mhnd = { m_shmid, true}; return mhnd; } inline bool xsi_shared_memory::priv_open_or_create - (detail::create_enum_t type, const char *filename, boost::uint8_t id, int perm, std::size_t size) + (detail::create_enum_t type, const xsi_key &key, const permissions& permissions, std::size_t size) { - key_t key; - if(filename){ - key = ::ftok(filename, id); - if(((key_t)-1) == key){ - error_info err = system_error_code(); - throw interprocess_exception(err); - } - } - else{ - key = IPC_PRIVATE; - } - + int perm = permissions.get_permissions(); perm &= 0x01FF; int shmflg = perm; @@ -192,7 +171,7 @@ inline bool xsi_shared_memory::priv_open_or_create } } - int ret = ::shmget(key, size, shmflg); + int ret = ::shmget(key.get_key(), size, shmflg); int shmid = ret; if((type == detail::DoOpen) && (-1 != ret)){ //Now get the size