1 /* Copyright 2006-2020 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/flyweight for library home page. 7 */ 8 9 #ifndef BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP 10 #define BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ 17 #include <boost/core/no_exceptions_support.hpp> 18 #include <boost/detail/workaround.hpp> 19 #include <boost/flyweight/detail/perfect_fwd.hpp> 20 #include <boost/mpl/apply.hpp> 21 22 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) 23 #pragma warning(push) 24 #pragma warning(disable:4101) /* unreferenced local vars */ 25 #endif 26 27 /* flyweight_core provides the inner implementation of flyweight<> by 28 * weaving together a value policy, a flyweight factory, a holder for the 29 * factory,a tracking policy and a locking policy. 30 */ 31 32 namespace boost{ 33 34 namespace flyweights{ 35 36 namespace detail{ 37 38 template< 39 typename ValuePolicy,typename Tag,typename TrackingPolicy, 40 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 41 > 42 class flyweight_core; 43 44 template< 45 typename ValuePolicy,typename Tag,typename TrackingPolicy, 46 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 47 > 48 struct flyweight_core_tracking_helper 49 { 50 private: 51 typedef flyweight_core< 52 ValuePolicy,Tag,TrackingPolicy, 53 FactorySpecifier,LockingPolicy, 54 HolderSpecifier 55 > core; 56 typedef typename core::handle_type handle_type; 57 typedef typename core::entry_type entry_type; 58 59 public: entryboost::flyweights::detail::flyweight_core_tracking_helper60 static const entry_type& entry(const handle_type& h) 61 { 62 return core::entry(h); 63 } 64 65 template<typename Checker> eraseboost::flyweights::detail::flyweight_core_tracking_helper66 static void erase(const handle_type& h,Checker chk) 67 { 68 typedef typename core::lock_type lock_type; 69 core::init(); 70 lock_type lock(core::mutex());(void)lock; 71 if(chk(h))core::factory().erase(h); 72 } 73 }; 74 75 template< 76 typename ValuePolicy,typename Tag,typename TrackingPolicy, 77 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 78 > 79 class flyweight_core 80 { 81 public: 82 typedef typename ValuePolicy::key_type key_type; 83 typedef typename ValuePolicy::value_type value_type; 84 typedef typename ValuePolicy::rep_type rep_type; 85 typedef typename mpl::apply2< 86 typename TrackingPolicy::entry_type, 87 rep_type, 88 key_type 89 >::type entry_type; 90 typedef typename mpl::apply2< 91 FactorySpecifier, 92 entry_type, 93 key_type 94 >::type factory_type; 95 typedef typename factory_type::handle_type base_handle_type; 96 typedef typename mpl::apply2< 97 typename TrackingPolicy::handle_type, 98 base_handle_type, 99 flyweight_core_tracking_helper< 100 ValuePolicy,Tag,TrackingPolicy, 101 FactorySpecifier,LockingPolicy, 102 HolderSpecifier 103 > 104 >::type handle_type; 105 typedef typename LockingPolicy::mutex_type mutex_type; 106 typedef typename LockingPolicy::lock_type lock_type; 107 init()108 static bool init() 109 { 110 if(static_initializer)return true; 111 else{ 112 holder_arg& a=holder_type::get(); 113 static_factory_ptr=&a.factory; 114 static_mutex_ptr=&a.mutex; 115 static_initializer=(static_factory_ptr!=0); 116 return static_initializer; 117 } 118 } 119 120 /* insert overloads*/ 121 122 #define BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY(args) \ 123 { \ 124 return insert_rep(rep_type(BOOST_FLYWEIGHT_FORWARD(args))); \ 125 } 126 BOOST_FLYWEIGHT_PERFECT_FWD(static handle_type insert,BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY)127 BOOST_FLYWEIGHT_PERFECT_FWD( 128 static handle_type insert, 129 BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY) 130 131 #undef BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY 132 133 static handle_type insert(const value_type& x){return insert_value(x);} insert(value_type & x)134 static handle_type insert(value_type& x){return insert_value(x);} 135 136 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) insert(const value_type && x)137 static handle_type insert(const value_type&& x){return insert_value(x);} insert(value_type && x)138 static handle_type insert(value_type&& x){return insert_value(std::move(x));} 139 #endif 140 entry(const base_handle_type & h)141 static const entry_type& entry(const base_handle_type& h) 142 { 143 return factory().entry(h); 144 } 145 value(const handle_type & h)146 static const value_type& value(const handle_type& h) 147 { 148 return static_cast<const rep_type&>(entry(h)); 149 } 150 key(const handle_type & h)151 static const key_type& key(const handle_type& h) 152 { 153 return static_cast<const rep_type&>(entry(h)); 154 } 155 factory()156 static factory_type& factory() 157 { 158 return *static_factory_ptr; 159 } 160 mutex()161 static mutex_type& mutex() 162 { 163 return *static_mutex_ptr; 164 } 165 166 private: 167 struct holder_arg 168 { 169 factory_type factory; 170 mutex_type mutex; 171 }; 172 typedef typename mpl::apply1< 173 HolderSpecifier, 174 holder_arg 175 >::type holder_type; 176 insert_rep(const rep_type & x)177 static handle_type insert_rep(const rep_type& x) 178 { 179 init(); 180 entry_type e(x); 181 lock_type lock(mutex());(void)lock; 182 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 183 base_handle_type h(factory().insert(std::move(e))); 184 #else 185 base_handle_type h(factory().insert(e)); 186 #endif 187 188 BOOST_TRY{ 189 ValuePolicy::construct_value( 190 static_cast<const rep_type&>(entry(h))); 191 } 192 BOOST_CATCH(...){ 193 factory().erase(h); 194 BOOST_RETHROW; 195 } 196 BOOST_CATCH_END 197 return static_cast<handle_type>(h); 198 } 199 insert_value(const value_type & x)200 static handle_type insert_value(const value_type& x) 201 { 202 init(); 203 entry_type e((rep_type(x))); 204 lock_type lock(mutex());(void)lock; 205 206 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 207 base_handle_type h(factory().insert(std::move(e))); 208 #else 209 base_handle_type h(factory().insert(e)); 210 #endif 211 212 BOOST_TRY{ 213 ValuePolicy::copy_value( 214 static_cast<const rep_type&>(entry(h))); 215 } 216 BOOST_CATCH(...){ 217 factory().erase(h); 218 BOOST_RETHROW; 219 } 220 BOOST_CATCH_END 221 return static_cast<handle_type>(h); 222 } 223 224 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) insert_rep(rep_type && x)225 static handle_type insert_rep(rep_type&& x) 226 { 227 init(); 228 entry_type e(std::move(x)); 229 lock_type lock(mutex());(void)lock; 230 base_handle_type h(factory().insert(std::move(e))); 231 232 BOOST_TRY{ 233 ValuePolicy::construct_value( 234 static_cast<const rep_type&>(entry(h))); 235 } 236 BOOST_CATCH(...){ 237 factory().erase(h); 238 BOOST_RETHROW; 239 } 240 BOOST_CATCH_END 241 return static_cast<handle_type>(h); 242 } 243 insert_value(value_type && x)244 static handle_type insert_value(value_type&& x) 245 { 246 init(); 247 entry_type e(rep_type(std::move(x))); 248 lock_type lock(mutex());(void)lock; 249 base_handle_type h(factory().insert(std::move(e))); 250 BOOST_TRY{ 251 ValuePolicy::move_value( 252 static_cast<const rep_type&>(entry(h))); 253 } 254 BOOST_CATCH(...){ 255 factory().erase(h); 256 BOOST_RETHROW; 257 } 258 BOOST_CATCH_END 259 return static_cast<handle_type>(h); 260 } 261 #endif 262 263 static bool static_initializer; 264 static factory_type* static_factory_ptr; 265 static mutex_type* static_mutex_ptr; 266 }; 267 268 template< 269 typename ValuePolicy,typename Tag,typename TrackingPolicy, 270 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 271 > 272 bool 273 flyweight_core< 274 ValuePolicy,Tag,TrackingPolicy, 275 FactorySpecifier,LockingPolicy,HolderSpecifier>::static_initializer= 276 flyweight_core< 277 ValuePolicy,Tag,TrackingPolicy, 278 FactorySpecifier,LockingPolicy,HolderSpecifier>::init(); 279 280 template< 281 typename ValuePolicy,typename Tag,typename TrackingPolicy, 282 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 283 > 284 typename flyweight_core< 285 ValuePolicy,Tag,TrackingPolicy, 286 FactorySpecifier,LockingPolicy,HolderSpecifier>::factory_type* 287 flyweight_core< 288 ValuePolicy,Tag,TrackingPolicy, 289 FactorySpecifier,LockingPolicy,HolderSpecifier>::static_factory_ptr=0; 290 291 template< 292 typename ValuePolicy,typename Tag,typename TrackingPolicy, 293 typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier 294 > 295 typename flyweight_core< 296 ValuePolicy,Tag,TrackingPolicy, 297 FactorySpecifier,LockingPolicy,HolderSpecifier>::mutex_type* 298 flyweight_core< 299 ValuePolicy,Tag,TrackingPolicy, 300 FactorySpecifier,LockingPolicy,HolderSpecifier>::static_mutex_ptr=0; 301 302 } /* namespace flyweights::detail */ 303 304 } /* namespace flyweights */ 305 306 } /* namespace boost */ 307 308 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) 309 #pragma warning(pop) 310 #endif 311 312 #endif 313