////////////////////////////////////////////////////////////////////////////// | |
// | |
// (C) Copyright Ion Gaztanaga 2005-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_NAMED_PROXY_HPP | |
#define BOOST_INTERPROCESS_NAMED_PROXY_HPP | |
#if (defined _MSC_VER) && (_MSC_VER >= 1200) | |
# pragma once | |
#endif | |
#include <boost/interprocess/detail/config_begin.hpp> | |
#include <boost/interprocess/detail/workaround.hpp> | |
#include <new> | |
#include <iterator> | |
#include <boost/interprocess/detail/in_place_interface.hpp> | |
#include <boost/interprocess/detail/mpl.hpp> | |
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING | |
#include <boost/interprocess/detail/preprocessor.hpp> | |
#else | |
#include <boost/interprocess/detail/move.hpp> | |
#include <boost/interprocess/detail/variadic_templates_tools.hpp> | |
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING | |
//!\file | |
//!Describes a proxy class that implements named allocation syntax. | |
namespace boost { | |
namespace interprocess { | |
namespace detail { | |
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING | |
template<class T, bool is_iterator, class ...Args> | |
struct CtorNArg : public placement_destroy<T> | |
{ | |
typedef detail::bool_<is_iterator> IsIterator; | |
typedef CtorNArg<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; } | |
CtorNArg(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<int ...IdxPack> | |
void construct(void *mem, detail::true_, const index_tuple<IdxPack...>&) | |
{ new((void*)mem)T(*boost::interprocess::forward<Args>(get<IdxPack>(args_))...); } | |
template<int ...IdxPack> | |
void construct(void *mem, detail::false_, const index_tuple<IdxPack...>&) | |
{ new((void*)mem)T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...); } | |
template<int ...IdxPack> | |
void do_increment(detail::true_, const index_tuple<IdxPack...>&) | |
{ | |
this->expansion_helper(++get<IdxPack>(args_)...); | |
} | |
template<class ...ExpansionArgs> | |
void expansion_helper(ExpansionArgs &&...) | |
{} | |
template<int ...IdxPack> | |
void do_increment(detail::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 | |
{ | |
CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...> | |
(boost::interprocess::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 | |
//!Function object that makes placement new | |
//!without arguments | |
template<class T> | |
struct Ctor0Arg : public placement_destroy<T> | |
{ | |
typedef Ctor0Arg self_t; | |
Ctor0Arg(){} | |
self_t& operator++() { return *this; } | |
self_t operator++(int) { return *this; } | |
void construct(void *mem) | |
{ new((void*)mem)T; } | |
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; | |
} | |
}; | |
//////////////////////////////////////////////////////////////// | |
// What the macro should generate (n == 2): | |
// | |
// template<class T, bool is_iterator, class P1, class P2> | |
// struct Ctor2Arg | |
// : public placement_destroy<T> | |
// { | |
// typedef detail::bool_<is_iterator> IsIterator; | |
// typedef Ctor2Arg self_t; | |
// | |
// void do_increment(detail::false_) | |
// { ++m_p1; ++m_p2; } | |
// | |
// void do_increment(detail::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, detail::true_) | |
// { new((void*)mem)T(*m_p1, *m_p2); } | |
// | |
// void construct(void *mem, detail::false_) | |
// { new((void*)mem)T(m_p1, m_p2); } | |
// | |
// P1 &m_p1; P2 &m_p2; | |
// }; | |
//////////////////////////////////////////////////////////////// | |
//Note: | |
//We define template parameters as const references to | |
//be able to bind temporaries. After that we will un-const them. | |
//This cast is ugly but it is necessary until "perfect forwarding" | |
//is achieved in C++0x. Meanwhile, if we want to be able to | |
//bind lvalues with non-const references, we have to be ugly | |
#define BOOST_PP_LOCAL_MACRO(n) \ | |
template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \ | |
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ | |
: public placement_destroy<T> \ | |
{ \ | |
typedef detail::bool_<is_iterator> IsIterator; \ | |
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \ | |
\ | |
void do_increment(detail::true_) \ | |
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \ | |
\ | |
void do_increment(detail::false_){} \ | |
\ | |
self_t& operator++() \ | |
{ \ | |
this->do_increment(IsIterator()); \ | |
return *this; \ | |
} \ | |
\ | |
self_t operator++(int) { return ++*this; *this; } \ | |
\ | |
BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ | |
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \ | |
: BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \ | |
\ | |
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, detail::true_) \ | |
{ \ | |
new((void*)mem) T \ | |
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \ | |
} \ | |
\ | |
void construct(void *mem, detail::false_) \ | |
{ \ | |
new((void*)mem) T \ | |
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \ | |
} \ | |
\ | |
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \ | |
}; \ | |
//! | |
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS) | |
#include BOOST_PP_LOCAL_ITERATE() | |
//!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) | |
{} | |
//!makes a named allocation and calls the | |
//!default constructor | |
T *operator()() const | |
{ | |
Ctor0Arg<T> ctor_obj; | |
return mp_mngr->template | |
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); | |
} | |
//! | |
#define BOOST_PP_LOCAL_MACRO(n) \ | |
template<BOOST_PP_ENUM_PARAMS(n, class P)> \ | |
T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\ | |
{ \ | |
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ | |
<T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \ | |
ctor_obj_t; \ | |
ctor_obj_t ctor_obj \ | |
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \ | |
return mp_mngr->template generic_construct<T> \ | |
(mp_name, m_num, m_find, m_dothrow, ctor_obj); \ | |
} \ | |
//! | |
#define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS ) | |
#include BOOST_PP_LOCAL_ITERATE() | |
//////////////////////////////////////////////////////////////////////// | |
// What the macro should generate (n == 2) | |
//////////////////////////////////////////////////////////////////////// | |
// | |
// template <class P1, class P2> | |
// T *operator()(P1 &p1, P2 &p2) const | |
// { | |
// typedef Ctor2Arg | |
// <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 detail { | |
#include <boost/interprocess/detail/config_end.hpp> | |
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP |