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