317 lines
10 KiB
C++
317 lines
10 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (C) Copyright Ion Gaztanaga 2005-2012. 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_NAMED_PROXY_HPP
|
|
#define BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
|
|
|
#ifndef BOOST_CONFIG_HPP
|
|
# include <boost/config.hpp>
|
|
#endif
|
|
#
|
|
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
|
# pragma once
|
|
#endif
|
|
|
|
#include <boost/interprocess/detail/config_begin.hpp>
|
|
#include <boost/interprocess/detail/workaround.hpp>
|
|
|
|
// interprocess/detail
|
|
#include <boost/interprocess/detail/in_place_interface.hpp>
|
|
#include <boost/interprocess/detail/mpl.hpp>
|
|
#include <boost/move/utility_core.hpp>
|
|
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
|
#include <boost/move/detail/fwd_macros.hpp>
|
|
#else
|
|
#include <boost/move/utility_core.hpp>
|
|
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
|
|
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
|
#include <boost/container/detail/placement_new.hpp>
|
|
|
|
#include <cstddef>
|
|
|
|
//!\file
|
|
//!Describes a proxy class that implements named allocation syntax.
|
|
|
|
namespace boost {
|
|
namespace interprocess {
|
|
namespace ipcdetail {
|
|
|
|
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
|
|
|
template<class T, bool is_iterator, class ...Args>
|
|
struct CtorArgN : public placement_destroy<T>
|
|
{
|
|
typedef bool_<is_iterator> IsIterator;
|
|
typedef CtorArgN<T, is_iterator, Args...> self_t;
|
|
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
|
|
|
self_t& operator++()
|
|
{
|
|
this->do_increment(IsIterator(), index_tuple_t());
|
|
return *this;
|
|
}
|
|
|
|
self_t operator++(int) { return ++*this; *this; }
|
|
|
|
CtorArgN(Args && ...args)
|
|
: args_(args...)
|
|
{}
|
|
|
|
virtual void construct_n(void *mem
|
|
, std::size_t num
|
|
, std::size_t &constructed)
|
|
{
|
|
T* memory = static_cast<T*>(mem);
|
|
for(constructed = 0; constructed < num; ++constructed){
|
|
this->construct(memory++, IsIterator(), index_tuple_t());
|
|
this->do_increment(IsIterator(), index_tuple_t());
|
|
}
|
|
}
|
|
|
|
private:
|
|
template<std::size_t ...IdxPack>
|
|
void construct(void *mem, true_, const index_tuple<IdxPack...>&)
|
|
{ ::new((void*)mem, boost_container_new_t())T(*boost::forward<Args>(get<IdxPack>(args_))...); }
|
|
|
|
template<std::size_t ...IdxPack>
|
|
void construct(void *mem, false_, const index_tuple<IdxPack...>&)
|
|
{ ::new((void*)mem, boost_container_new_t())T(boost::forward<Args>(get<IdxPack>(args_))...); }
|
|
|
|
template<std::size_t ...IdxPack>
|
|
void do_increment(true_, const index_tuple<IdxPack...>&)
|
|
{
|
|
this->expansion_helper(++get<IdxPack>(args_)...);
|
|
}
|
|
|
|
template<class ...ExpansionArgs>
|
|
void expansion_helper(ExpansionArgs &&...)
|
|
{}
|
|
|
|
template<std::size_t ...IdxPack>
|
|
void do_increment(false_, const index_tuple<IdxPack...>&)
|
|
{}
|
|
|
|
tuple<Args&...> args_;
|
|
};
|
|
|
|
//!Describes a proxy class that implements named
|
|
//!allocation syntax.
|
|
template
|
|
< class SegmentManager //segment manager to construct the object
|
|
, class T //type of object to build
|
|
, bool is_iterator //passing parameters are normal object or iterators?
|
|
>
|
|
class named_proxy
|
|
{
|
|
typedef typename SegmentManager::char_type char_type;
|
|
const char_type * mp_name;
|
|
SegmentManager * mp_mngr;
|
|
mutable std::size_t m_num;
|
|
const bool m_find;
|
|
const bool m_dothrow;
|
|
|
|
public:
|
|
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
|
: mp_name(name), mp_mngr(mngr), m_num(1)
|
|
, m_find(find), m_dothrow(dothrow)
|
|
{}
|
|
|
|
template<class ...Args>
|
|
T *operator()(Args &&...args) const
|
|
{
|
|
CtorArgN<T, is_iterator, Args...> &&ctor_obj = CtorArgN<T, is_iterator, Args...>
|
|
(boost::forward<Args>(args)...);
|
|
return mp_mngr->template
|
|
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
|
}
|
|
|
|
//This operator allows --> named_new("Name")[3]; <-- syntax
|
|
const named_proxy &operator[](std::size_t num) const
|
|
{ m_num *= num; return *this; }
|
|
};
|
|
|
|
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// What the macro should generate (n == 2):
|
|
//
|
|
// template<class T, bool is_iterator, class P1, class P2>
|
|
// struct Ctor2Arg
|
|
// : public placement_destroy<T>
|
|
// {
|
|
// typedef bool_<is_iterator> IsIterator;
|
|
// typedef Ctor2Arg self_t;
|
|
//
|
|
// void do_increment(false_)
|
|
// { ++m_p1; ++m_p2; }
|
|
//
|
|
// void do_increment(true_){}
|
|
//
|
|
// self_t& operator++()
|
|
// {
|
|
// this->do_increment(IsIterator());
|
|
// return *this;
|
|
// }
|
|
//
|
|
// self_t operator++(int) { return ++*this; *this; }
|
|
//
|
|
// Ctor2Arg(const P1 &p1, const P2 &p2)
|
|
// : p1((P1 &)p_1), p2((P2 &)p_2) {}
|
|
//
|
|
// void construct(void *mem)
|
|
// { new((void*)object)T(m_p1, m_p2); }
|
|
//
|
|
// virtual void construct_n(void *mem
|
|
// , std::size_t num
|
|
// , std::size_t &constructed)
|
|
// {
|
|
// T* memory = static_cast<T*>(mem);
|
|
// for(constructed = 0; constructed < num; ++constructed){
|
|
// this->construct(memory++, IsIterator());
|
|
// this->do_increment(IsIterator());
|
|
// }
|
|
// }
|
|
//
|
|
// private:
|
|
// void construct(void *mem, true_)
|
|
// { new((void*)mem)T(*m_p1, *m_p2); }
|
|
//
|
|
// void construct(void *mem, false_)
|
|
// { new((void*)mem)T(m_p1, m_p2); }
|
|
//
|
|
// P1 &m_p1; P2 &m_p2;
|
|
// };
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\
|
|
\
|
|
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
|
struct CtorArg##N : placement_destroy<T>\
|
|
{\
|
|
typedef CtorArg##N self_t;\
|
|
\
|
|
CtorArg##N ( BOOST_MOVE_UREF##N )\
|
|
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
|
|
\
|
|
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
|
|
{\
|
|
T* memory = static_cast<T*>(mem);\
|
|
for(constructed = 0; constructed < num; ++constructed){\
|
|
::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\
|
|
}\
|
|
}\
|
|
\
|
|
private:\
|
|
BOOST_MOVE_MREF##N\
|
|
};\
|
|
//!
|
|
BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN)
|
|
#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN
|
|
|
|
#define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\
|
|
\
|
|
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
|
struct CtorIt##N : public placement_destroy<T>\
|
|
{\
|
|
typedef CtorIt##N self_t;\
|
|
\
|
|
self_t& operator++()\
|
|
{ BOOST_MOVE_MINC##N; return *this; }\
|
|
\
|
|
self_t operator++(int) { return ++*this; *this; }\
|
|
\
|
|
CtorIt##N ( BOOST_MOVE_VAL##N )\
|
|
BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
|
|
\
|
|
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
|
|
{\
|
|
T* memory = static_cast<T*>(mem);\
|
|
for(constructed = 0; constructed < num; ++constructed){\
|
|
::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\
|
|
++(*this);\
|
|
}\
|
|
}\
|
|
\
|
|
private:\
|
|
BOOST_MOVE_MEMB##N\
|
|
};\
|
|
//!
|
|
BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN)
|
|
#undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN
|
|
|
|
//!Describes a proxy class that implements named
|
|
//!allocation syntax.
|
|
template
|
|
< class SegmentManager //segment manager to construct the object
|
|
, class T //type of object to build
|
|
, bool is_iterator //passing parameters are normal object or iterators?
|
|
>
|
|
class named_proxy
|
|
{
|
|
typedef typename SegmentManager::char_type char_type;
|
|
const char_type * mp_name;
|
|
SegmentManager * mp_mngr;
|
|
mutable std::size_t m_num;
|
|
const bool m_find;
|
|
const bool m_dothrow;
|
|
|
|
public:
|
|
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
|
: mp_name(name), mp_mngr(mngr), m_num(1)
|
|
, m_find(find), m_dothrow(dothrow)
|
|
{}
|
|
|
|
#define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\
|
|
\
|
|
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
|
T *operator()( BOOST_MOVE_UREF##N ) const\
|
|
{\
|
|
typedef typename if_c<is_iterator \
|
|
, CtorIt##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
|
|
, CtorArg##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
|
|
>::type ctor_obj_t;\
|
|
ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\
|
|
return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);\
|
|
}\
|
|
//
|
|
BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR)
|
|
#undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// What the macro should generate (n == 2)
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// template <class P1, class P2>
|
|
// T *operator()(P1 &p1, P2 &p2) const
|
|
// {
|
|
// typedef CtorArg2
|
|
// <T, is_iterator, P1, P2>
|
|
// ctor_obj_t;
|
|
// ctor_obj_t ctor_obj(p1, p2);
|
|
//
|
|
// return mp_mngr->template generic_construct<T>
|
|
// (mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
|
// }
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//This operator allows --> named_new("Name")[3]; <-- syntax
|
|
const named_proxy &operator[](std::size_t num) const
|
|
{ m_num *= num; return *this; }
|
|
};
|
|
|
|
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
|
|
|
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
|
|
|
#include <boost/interprocess/detail/config_end.hpp>
|
|
|
|
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|