named_proxy.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
  11. #define BOOST_INTERPROCESS_NAMED_PROXY_HPP
  12. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include <boost/interprocess/detail/config_begin.hpp>
  16. #include <boost/interprocess/detail/workaround.hpp>
  17. #include <new>
  18. #include <iterator>
  19. #include <boost/interprocess/detail/in_place_interface.hpp>
  20. #include <boost/interprocess/detail/mpl.hpp>
  21. #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
  22. #include <boost/interprocess/detail/preprocessor.hpp>
  23. #else
  24. #include <boost/move/move.hpp>
  25. #include <boost/interprocess/detail/variadic_templates_tools.hpp>
  26. #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
  27. //!\file
  28. //!Describes a proxy class that implements named allocation syntax.
  29. namespace boost {
  30. namespace interprocess {
  31. namespace ipcdetail {
  32. #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
  33. template<class T, bool is_iterator, class ...Args>
  34. struct CtorNArg : public placement_destroy<T>
  35. {
  36. typedef bool_<is_iterator> IsIterator;
  37. typedef CtorNArg<T, is_iterator, Args...> self_t;
  38. typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
  39. self_t& operator++()
  40. {
  41. this->do_increment(IsIterator(), index_tuple_t());
  42. return *this;
  43. }
  44. self_t operator++(int) { return ++*this; *this; }
  45. CtorNArg(Args && ...args)
  46. : args_(args...)
  47. {}
  48. virtual void construct_n(void *mem
  49. , std::size_t num
  50. , std::size_t &constructed)
  51. {
  52. T* memory = static_cast<T*>(mem);
  53. for(constructed = 0; constructed < num; ++constructed){
  54. this->construct(memory++, IsIterator(), index_tuple_t());
  55. this->do_increment(IsIterator(), index_tuple_t());
  56. }
  57. }
  58. private:
  59. template<int ...IdxPack>
  60. void construct(void *mem, true_, const index_tuple<IdxPack...>&)
  61. { new((void*)mem)T(*boost::forward<Args>(get<IdxPack>(args_))...); }
  62. template<int ...IdxPack>
  63. void construct(void *mem, false_, const index_tuple<IdxPack...>&)
  64. { new((void*)mem)T(boost::forward<Args>(get<IdxPack>(args_))...); }
  65. template<int ...IdxPack>
  66. void do_increment(true_, const index_tuple<IdxPack...>&)
  67. {
  68. this->expansion_helper(++get<IdxPack>(args_)...);
  69. }
  70. template<class ...ExpansionArgs>
  71. void expansion_helper(ExpansionArgs &&...)
  72. {}
  73. template<int ...IdxPack>
  74. void do_increment(false_, const index_tuple<IdxPack...>&)
  75. {}
  76. tuple<Args&...> args_;
  77. };
  78. //!Describes a proxy class that implements named
  79. //!allocation syntax.
  80. template
  81. < class SegmentManager //segment manager to construct the object
  82. , class T //type of object to build
  83. , bool is_iterator //passing parameters are normal object or iterators?
  84. >
  85. class named_proxy
  86. {
  87. typedef typename SegmentManager::char_type char_type;
  88. const char_type * mp_name;
  89. SegmentManager * mp_mngr;
  90. mutable std::size_t m_num;
  91. const bool m_find;
  92. const bool m_dothrow;
  93. public:
  94. named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
  95. : mp_name(name), mp_mngr(mngr), m_num(1)
  96. , m_find(find), m_dothrow(dothrow)
  97. {}
  98. template<class ...Args>
  99. T *operator()(Args &&...args) const
  100. {
  101. CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
  102. (boost::forward<Args>(args)...);
  103. return mp_mngr->template
  104. generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
  105. }
  106. //This operator allows --> named_new("Name")[3]; <-- syntax
  107. const named_proxy &operator[](std::size_t num) const
  108. { m_num *= num; return *this; }
  109. };
  110. #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
  111. //!Function object that makes placement new
  112. //!without arguments
  113. template<class T>
  114. struct Ctor0Arg : public placement_destroy<T>
  115. {
  116. typedef Ctor0Arg self_t;
  117. Ctor0Arg(){}
  118. self_t& operator++() { return *this; }
  119. self_t operator++(int) { return *this; }
  120. void construct(void *mem)
  121. { new((void*)mem)T; }
  122. virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
  123. {
  124. T* memory = static_cast<T*>(mem);
  125. for(constructed = 0; constructed < num; ++constructed)
  126. new((void*)memory++)T;
  127. }
  128. };
  129. ////////////////////////////////////////////////////////////////
  130. // What the macro should generate (n == 2):
  131. //
  132. // template<class T, bool is_iterator, class P1, class P2>
  133. // struct Ctor2Arg
  134. // : public placement_destroy<T>
  135. // {
  136. // typedef bool_<is_iterator> IsIterator;
  137. // typedef Ctor2Arg self_t;
  138. //
  139. // void do_increment(false_)
  140. // { ++m_p1; ++m_p2; }
  141. //
  142. // void do_increment(true_){}
  143. //
  144. // self_t& operator++()
  145. // {
  146. // this->do_increment(IsIterator());
  147. // return *this;
  148. // }
  149. //
  150. // self_t operator++(int) { return ++*this; *this; }
  151. //
  152. // Ctor2Arg(const P1 &p1, const P2 &p2)
  153. // : p1((P1 &)p_1), p2((P2 &)p_2) {}
  154. //
  155. // void construct(void *mem)
  156. // { new((void*)object)T(m_p1, m_p2); }
  157. //
  158. // virtual void construct_n(void *mem
  159. // , std::size_t num
  160. // , std::size_t &constructed)
  161. // {
  162. // T* memory = static_cast<T*>(mem);
  163. // for(constructed = 0; constructed < num; ++constructed){
  164. // this->construct(memory++, IsIterator());
  165. // this->do_increment(IsIterator());
  166. // }
  167. // }
  168. //
  169. // private:
  170. // void construct(void *mem, true_)
  171. // { new((void*)mem)T(*m_p1, *m_p2); }
  172. //
  173. // void construct(void *mem, false_)
  174. // { new((void*)mem)T(m_p1, m_p2); }
  175. //
  176. // P1 &m_p1; P2 &m_p2;
  177. // };
  178. ////////////////////////////////////////////////////////////////
  179. //Note:
  180. //We define template parameters as const references to
  181. //be able to bind temporaries. After that we will un-const them.
  182. //This cast is ugly but it is necessary until "perfect forwarding"
  183. //is achieved in C++0x. Meanwhile, if we want to be able to
  184. //bind lvalues with non-const references, we have to be ugly
  185. #define BOOST_PP_LOCAL_MACRO(n) \
  186. template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
  187. struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
  188. : public placement_destroy<T> \
  189. { \
  190. typedef bool_<is_iterator> IsIterator; \
  191. typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
  192. \
  193. void do_increment(true_) \
  194. { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); } \
  195. \
  196. void do_increment(false_){} \
  197. \
  198. self_t& operator++() \
  199. { \
  200. this->do_increment(IsIterator()); \
  201. return *this; \
  202. } \
  203. \
  204. self_t operator++(int) { return ++*this; *this; } \
  205. \
  206. BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
  207. ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
  208. : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {} \
  209. \
  210. virtual void construct_n(void *mem \
  211. , std::size_t num \
  212. , std::size_t &constructed) \
  213. { \
  214. T* memory = static_cast<T*>(mem); \
  215. for(constructed = 0; constructed < num; ++constructed){ \
  216. this->construct(memory++, IsIterator()); \
  217. this->do_increment(IsIterator()); \
  218. } \
  219. } \
  220. \
  221. private: \
  222. void construct(void *mem, true_) \
  223. { \
  224. new((void*)mem) T \
  225. (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
  226. } \
  227. \
  228. void construct(void *mem, false_) \
  229. { \
  230. new((void*)mem) T \
  231. (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
  232. } \
  233. \
  234. BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _) \
  235. }; \
  236. //!
  237. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
  238. #include BOOST_PP_LOCAL_ITERATE()
  239. //!Describes a proxy class that implements named
  240. //!allocation syntax.
  241. template
  242. < class SegmentManager //segment manager to construct the object
  243. , class T //type of object to build
  244. , bool is_iterator //passing parameters are normal object or iterators?
  245. >
  246. class named_proxy
  247. {
  248. typedef typename SegmentManager::char_type char_type;
  249. const char_type * mp_name;
  250. SegmentManager * mp_mngr;
  251. mutable std::size_t m_num;
  252. const bool m_find;
  253. const bool m_dothrow;
  254. public:
  255. named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
  256. : mp_name(name), mp_mngr(mngr), m_num(1)
  257. , m_find(find), m_dothrow(dothrow)
  258. {}
  259. //!makes a named allocation and calls the
  260. //!default constructor
  261. T *operator()() const
  262. {
  263. Ctor0Arg<T> ctor_obj;
  264. return mp_mngr->template
  265. generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
  266. }
  267. //!
  268. #define BOOST_PP_LOCAL_MACRO(n) \
  269. template<BOOST_PP_ENUM_PARAMS(n, class P)> \
  270. T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
  271. { \
  272. typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
  273. <T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
  274. ctor_obj_t; \
  275. ctor_obj_t ctor_obj \
  276. (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
  277. return mp_mngr->template generic_construct<T> \
  278. (mp_name, m_num, m_find, m_dothrow, ctor_obj); \
  279. } \
  280. //!
  281. #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
  282. #include BOOST_PP_LOCAL_ITERATE()
  283. ////////////////////////////////////////////////////////////////////////
  284. // What the macro should generate (n == 2)
  285. ////////////////////////////////////////////////////////////////////////
  286. //
  287. // template <class P1, class P2>
  288. // T *operator()(P1 &p1, P2 &p2) const
  289. // {
  290. // typedef Ctor2Arg
  291. // <T, is_iterator, P1, P2>
  292. // ctor_obj_t;
  293. // ctor_obj_t ctor_obj(p1, p2);
  294. //
  295. // return mp_mngr->template generic_construct<T>
  296. // (mp_name, m_num, m_find, m_dothrow, ctor_obj);
  297. // }
  298. //
  299. //////////////////////////////////////////////////////////////////////////
  300. //This operator allows --> named_new("Name")[3]; <-- syntax
  301. const named_proxy &operator[](std::size_t num) const
  302. { m_num *= num; return *this; }
  303. };
  304. #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
  305. }}} //namespace boost { namespace interprocess { namespace ipcdetail {
  306. #include <boost/interprocess/detail/config_end.hpp>
  307. #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP