You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
349 lines
14 KiB
349 lines
14 KiB
////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// (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 ipcdetail { |
|
|
|
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING |
|
|
|
template<class T, bool is_iterator, class ...Args> |
|
struct CtorNArg : public placement_destroy<T> |
|
{ |
|
typedef ipcdetail::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, ipcdetail::true_, const index_tuple<IdxPack...>&) |
|
{ new((void*)mem)T(*boost::interprocess::forward<Args>(get<IdxPack>(args_))...); } |
|
|
|
template<int ...IdxPack> |
|
void construct(void *mem, ipcdetail::false_, const index_tuple<IdxPack...>&) |
|
{ new((void*)mem)T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...); } |
|
|
|
template<int ...IdxPack> |
|
void do_increment(ipcdetail::true_, const index_tuple<IdxPack...>&) |
|
{ |
|
this->expansion_helper(++get<IdxPack>(args_)...); |
|
} |
|
|
|
template<class ...ExpansionArgs> |
|
void expansion_helper(ExpansionArgs &&...) |
|
{} |
|
|
|
template<int ...IdxPack> |
|
void do_increment(ipcdetail::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 ipcdetail::bool_<is_iterator> IsIterator; |
|
// typedef Ctor2Arg self_t; |
|
// |
|
// void do_increment(ipcdetail::false_) |
|
// { ++m_p1; ++m_p2; } |
|
// |
|
// void do_increment(ipcdetail::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, ipcdetail::true_) |
|
// { new((void*)mem)T(*m_p1, *m_p2); } |
|
// |
|
// void construct(void *mem, ipcdetail::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 ipcdetail::bool_<is_iterator> IsIterator; \ |
|
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \ |
|
\ |
|
void do_increment(ipcdetail::true_) \ |
|
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \ |
|
\ |
|
void do_increment(ipcdetail::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, ipcdetail::true_) \ |
|
{ \ |
|
new((void*)mem) T \ |
|
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \ |
|
} \ |
|
\ |
|
void construct(void *mem, ipcdetail::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 ipcdetail { |
|
|
|
#include <boost/interprocess/detail/config_end.hpp> |
|
|
|
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
|
|