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 11 #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP 12 #define BOOST_INTERPROCESS_NAMED_PROXY_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 # 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/interprocess/detail/config_begin.hpp> 23 #include <boost/interprocess/detail/workaround.hpp> 24 25 // interprocess/detail 26 #include <boost/interprocess/detail/in_place_interface.hpp> 27 #include <boost/interprocess/detail/mpl.hpp> 28 #include <boost/move/utility_core.hpp> 29 #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING 30 #include <boost/move/detail/fwd_macros.hpp> 31 #else 32 #include <boost/move/utility_core.hpp> 33 #include <boost/interprocess/detail/variadic_templates_tools.hpp> 34 #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING 35 #include <boost/container/detail/placement_new.hpp> 36 37 //!\file 38 //!Describes a proxy class that implements named allocation syntax. 39 40 namespace boost { 41 namespace interprocess { 42 namespace ipcdetail { 43 44 #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING 45 46 template<class T, bool is_iterator, class ...Args> 47 struct CtorArgN : public placement_destroy<T> 48 { 49 typedef bool_<is_iterator> IsIterator; 50 typedef CtorArgN<T, is_iterator, Args...> self_t; 51 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t; 52 operator ++boost::interprocess::ipcdetail::CtorArgN53 self_t& operator++() 54 { 55 this->do_increment(IsIterator(), index_tuple_t()); 56 return *this; 57 } 58 operator ++boost::interprocess::ipcdetail::CtorArgN59 self_t operator++(int) { return ++*this; *this; } 60 CtorArgNboost::interprocess::ipcdetail::CtorArgN61 CtorArgN(Args && ...args) 62 : args_(args...) 63 {} 64 construct_nboost::interprocess::ipcdetail::CtorArgN65 virtual void construct_n(void *mem 66 , std::size_t num 67 , std::size_t &constructed) 68 { 69 T* memory = static_cast<T*>(mem); 70 for(constructed = 0; constructed < num; ++constructed){ 71 this->construct(memory++, IsIterator(), index_tuple_t()); 72 this->do_increment(IsIterator(), index_tuple_t()); 73 } 74 } 75 76 private: 77 template<int ...IdxPack> constructboost::interprocess::ipcdetail::CtorArgN78 void construct(void *mem, true_, const index_tuple<IdxPack...>&) 79 { ::new((void*)mem, boost_container_new_t())T(*boost::forward<Args>(get<IdxPack>(args_))...); } 80 81 template<int ...IdxPack> constructboost::interprocess::ipcdetail::CtorArgN82 void construct(void *mem, false_, const index_tuple<IdxPack...>&) 83 { ::new((void*)mem, boost_container_new_t())T(boost::forward<Args>(get<IdxPack>(args_))...); } 84 85 template<int ...IdxPack> do_incrementboost::interprocess::ipcdetail::CtorArgN86 void do_increment(true_, const index_tuple<IdxPack...>&) 87 { 88 this->expansion_helper(++get<IdxPack>(args_)...); 89 } 90 91 template<class ...ExpansionArgs> expansion_helperboost::interprocess::ipcdetail::CtorArgN92 void expansion_helper(ExpansionArgs &&...) 93 {} 94 95 template<int ...IdxPack> do_incrementboost::interprocess::ipcdetail::CtorArgN96 void do_increment(false_, const index_tuple<IdxPack...>&) 97 {} 98 99 tuple<Args&...> args_; 100 }; 101 102 //!Describes a proxy class that implements named 103 //!allocation syntax. 104 template 105 < class SegmentManager //segment manager to construct the object 106 , class T //type of object to build 107 , bool is_iterator //passing parameters are normal object or iterators? 108 > 109 class named_proxy 110 { 111 typedef typename SegmentManager::char_type char_type; 112 const char_type * mp_name; 113 SegmentManager * mp_mngr; 114 mutable std::size_t m_num; 115 const bool m_find; 116 const bool m_dothrow; 117 118 public: named_proxy(SegmentManager * mngr,const char_type * name,bool find,bool dothrow)119 named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) 120 : mp_name(name), mp_mngr(mngr), m_num(1) 121 , m_find(find), m_dothrow(dothrow) 122 {} 123 124 template<class ...Args> operator ()(Args &&...args) const125 T *operator()(Args &&...args) const 126 { 127 CtorArgN<T, is_iterator, Args...> &&ctor_obj = CtorArgN<T, is_iterator, Args...> 128 (boost::forward<Args>(args)...); 129 return mp_mngr->template 130 generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); 131 } 132 133 //This operator allows --> named_new("Name")[3]; <-- syntax operator [](std::size_t num) const134 const named_proxy &operator[](std::size_t num) const 135 { m_num *= num; return *this; } 136 }; 137 138 #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING 139 140 //////////////////////////////////////////////////////////////// 141 // What the macro should generate (n == 2): 142 // 143 // template<class T, bool is_iterator, class P1, class P2> 144 // struct Ctor2Arg 145 // : public placement_destroy<T> 146 // { 147 // typedef bool_<is_iterator> IsIterator; 148 // typedef Ctor2Arg self_t; 149 // 150 // void do_increment(false_) 151 // { ++m_p1; ++m_p2; } 152 // 153 // void do_increment(true_){} 154 // 155 // self_t& operator++() 156 // { 157 // this->do_increment(IsIterator()); 158 // return *this; 159 // } 160 // 161 // self_t operator++(int) { return ++*this; *this; } 162 // 163 // Ctor2Arg(const P1 &p1, const P2 &p2) 164 // : p1((P1 &)p_1), p2((P2 &)p_2) {} 165 // 166 // void construct(void *mem) 167 // { new((void*)object)T(m_p1, m_p2); } 168 // 169 // virtual void construct_n(void *mem 170 // , std::size_t num 171 // , std::size_t &constructed) 172 // { 173 // T* memory = static_cast<T*>(mem); 174 // for(constructed = 0; constructed < num; ++constructed){ 175 // this->construct(memory++, IsIterator()); 176 // this->do_increment(IsIterator()); 177 // } 178 // } 179 // 180 // private: 181 // void construct(void *mem, true_) 182 // { new((void*)mem)T(*m_p1, *m_p2); } 183 // 184 // void construct(void *mem, false_) 185 // { new((void*)mem)T(m_p1, m_p2); } 186 // 187 // P1 &m_p1; P2 &m_p2; 188 // }; 189 //////////////////////////////////////////////////////////////// 190 191 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN(N)\ 192 \ 193 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ 194 struct CtorArg##N : placement_destroy<T>\ 195 {\ 196 typedef CtorArg##N self_t;\ 197 \ 198 CtorArg##N ( BOOST_MOVE_UREF##N )\ 199 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\ 200 \ 201 virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\ 202 {\ 203 T* memory = static_cast<T*>(mem);\ 204 for(constructed = 0; constructed < num; ++constructed){\ 205 ::new((void*)memory++) T ( BOOST_MOVE_MFWD##N );\ 206 }\ 207 }\ 208 \ 209 private:\ 210 BOOST_MOVE_MREF##N\ 211 };\ 212 //! 213 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN) 214 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORARGN 215 216 #define BOOST_INTERPROCESS_NAMED_PROXY_CTORITN(N)\ 217 \ 218 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ 219 struct CtorIt##N : public placement_destroy<T>\ 220 {\ 221 typedef CtorIt##N self_t;\ 222 \ 223 self_t& operator++()\ 224 { BOOST_MOVE_MINC##N; return *this; }\ 225 \ 226 self_t operator++(int) { return ++*this; *this; }\ 227 \ 228 CtorIt##N ( BOOST_MOVE_VAL##N )\ 229 BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\ 230 \ 231 virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\ 232 {\ 233 T* memory = static_cast<T*>(mem);\ 234 for(constructed = 0; constructed < num; ++constructed){\ 235 ::new((void*)memory++) T( BOOST_MOVE_MITFWD##N );\ 236 ++(*this);\ 237 }\ 238 }\ 239 \ 240 private:\ 241 BOOST_MOVE_MEMB##N\ 242 };\ 243 //! 244 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CTORITN) 245 #undef BOOST_INTERPROCESS_NAMED_PROXY_CTORITN 246 247 //!Describes a proxy class that implements named 248 //!allocation syntax. 249 template 250 < class SegmentManager //segment manager to construct the object 251 , class T //type of object to build 252 , bool is_iterator //passing parameters are normal object or iterators? 253 > 254 class named_proxy 255 { 256 typedef typename SegmentManager::char_type char_type; 257 const char_type * mp_name; 258 SegmentManager * mp_mngr; 259 mutable std::size_t m_num; 260 const bool m_find; 261 const bool m_dothrow; 262 263 public: 264 named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) 265 : mp_name(name), mp_mngr(mngr), m_num(1) 266 , m_find(find), m_dothrow(dothrow) 267 {} 268 269 #define BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR(N)\ 270 \ 271 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 272 T *operator()( BOOST_MOVE_UREF##N ) const\ 273 {\ 274 typedef typename if_c<is_iterator \ 275 , CtorIt##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \ 276 , CtorArg##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \ 277 >::type ctor_obj_t;\ 278 ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\ 279 return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);\ 280 }\ 281 // 282 BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR) 283 #undef BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR 284 285 //////////////////////////////////////////////////////////////////////// 286 // What the macro should generate (n == 2) 287 //////////////////////////////////////////////////////////////////////// 288 // 289 // template <class P1, class P2> 290 // T *operator()(P1 &p1, P2 &p2) const 291 // { 292 // typedef CtorArg2 293 // <T, is_iterator, P1, P2> 294 // ctor_obj_t; 295 // ctor_obj_t ctor_obj(p1, p2); 296 // 297 // return mp_mngr->template generic_construct<T> 298 // (mp_name, m_num, m_find, m_dothrow, ctor_obj); 299 // } 300 // 301 ////////////////////////////////////////////////////////////////////////// 302 303 //This operator allows --> named_new("Name")[3]; <-- syntax 304 const named_proxy &operator[](std::size_t num) const 305 { m_num *= num; return *this; } 306 }; 307 308 #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING 309 310 }}} //namespace boost { namespace interprocess { namespace ipcdetail { 311 312 #include <boost/interprocess/detail/config_end.hpp> 313 314 #endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP 315