Added XSI shared memory

[SVN r67449]
This commit is contained in:
Ion Gaztañaga
2010-12-26 09:47:54 +00:00
parent d83cd2023c
commit a86d42120e
13 changed files with 612 additions and 167 deletions

View File

@@ -35,4 +35,6 @@ using boost::container::ordered_unique_range;
#include <boost/interprocess/detail/config_end.hpp>
/// @endcond
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP

View File

@@ -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.

View File

@@ -30,16 +30,66 @@ namespace interprocess {
/// @cond
namespace detail{ class interprocess_tester; }
template<class DeviceAbstraction>
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<xsi_shared_memory_file_wrapper>
{
typedef xsi_key type;
};
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
/// @endcond
namespace detail {
template<class DeviceAbstraction, bool FileBased = true>
template <bool StoreDevice, class DeviceAbstraction>
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 DeviceAbstraction>
class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
{
public:
DeviceAbstraction &get_device()
{ return dev; }
const DeviceAbstraction &get_device() const
{ return dev; }
private:
DeviceAbstraction dev;
};
template<class DeviceAbstraction, bool FileBased = true, bool StoreDevice = true>
class managed_open_or_create_impl
: public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
{
//Non-copyable
BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t;
typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> 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 <class ConstructFunc>
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 <class ConstructFunc>
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 <class ConstructFunc>
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<bool dummy>
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<bool dummy>
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 <class ConstructFunc> 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<FileBased>(dev, m_name.c_str(), size, perm, file_like_t());
create_device<FileBased>(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<FileBased>(dev, m_name.c_str(), size, perm, file_like_t());
create_device<FileBased>(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<class DeviceAbstraction>

View File

@@ -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)

View File

@@ -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<class Object>
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_IG> 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_IG> 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_IG> 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_IG> 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;
}

View File

@@ -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 <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/xsi_shared_memory.hpp>
#include <boost/interprocess/xsi_shared_memory.hpp>
#include <boost/interprocess/sync/xsi/xsi_named_mutex.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
@@ -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();

View File

@@ -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 <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
#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 <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/xsi_shared_memory.hpp>
//!\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 <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP

View File

@@ -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 <class CharType
,class MemoryAlgorithm
@@ -258,9 +258,10 @@ typedef basic_managed_windows_shared_memory
,iset_index>
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 CharType
,class MemoryAlgorithm
,template<class IndexConfig> class IndexType>
@@ -277,9 +278,8 @@ typedef basic_managed_xsi_shared_memory
,rbtree_best_fit<mutex_family>
,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

View File

@@ -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 <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#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 <boost/interprocess/detail/managed_memory_impl.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp>
#include <boost/interprocess/creation_tags.hpp>
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<CharType, AllocationAlgorithm, IndexType>*/
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
class basic_managed_xsi_shared_memory
: public detail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
,detail::managed_open_or_create_impl<xsi_shared_memory_file_wrapper, false, true>::ManagedOpenOrCreateUserOffset>
, private detail::managed_open_or_create_impl<xsi_shared_memory_file_wrapper, false, true>
{
/// @cond
public:
typedef xsi_shared_memory_file_wrapper device_type;
public:
typedef detail::managed_open_or_create_impl
<xsi_shared_memory_file_wrapper, false, true> base2_t;
typedef detail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
base2_t::ManagedOpenOrCreateUserOffset> base_t;
typedef detail::create_open_func<base_t> 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 <class T>
std::pair<T*, std::size_t> find (char_ptr_holder_t name)
{
if(base2_t::get_mapped_region().get_mode() == read_only){
return base_t::template find_no_lock<T>(name);
}
else{
return base_t::template find<T>(name);
}
}
/// @endcond
};
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP

View File

@@ -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<Dummy>:
#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 <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_PERMISSIONS_HPP

View File

@@ -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

View File

@@ -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 <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
#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 <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <sys/types.h>
#include <sys/ipc.h>
#include <cstddef>
#include <boost/cstdint.hpp>
//!\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 <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_XSI_KEY_HPP

View File

@@ -15,20 +15,22 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
#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 <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/xsi_key.hpp>
#include <boost/interprocess/permissions.hpp>
#include <sys/shm.h>
#include <cstddef>
#include <boost/cstdint.hpp>
#include <string>
//!\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