Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/flyweight/detail/flyweight_core.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* Copyright 2006-2024 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/flyweight for library home page.
0007  */
0008 
0009 #ifndef BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
0010 #define BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/core/no_exceptions_support.hpp>
0018 #include <boost/config/workaround.hpp>
0019 #include <boost/flyweight/detail/perfect_fwd.hpp>
0020 #include <boost/mpl/apply.hpp>
0021 #include <boost/type_traits/declval.hpp>
0022 #include <utility>
0023 
0024 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
0025 #pragma warning(push)
0026 #pragma warning(disable:4101)  /* unreferenced local vars */
0027 #endif
0028 
0029 /* flyweight_core provides the inner implementation of flyweight<> by
0030  * weaving together a value policy, a flyweight factory, a holder for the
0031  * factory,a tracking policy and a locking policy.
0032  */
0033 
0034 namespace boost{
0035 
0036 namespace flyweights{
0037 
0038 namespace detail{
0039 
0040 template<
0041   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0042   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0043 >
0044 class flyweight_core;
0045 
0046 template<
0047   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0048   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0049 >
0050 struct flyweight_core_tracking_helper
0051 {
0052 private:
0053   typedef flyweight_core<
0054     ValuePolicy,Tag,TrackingPolicy,
0055     FactorySpecifier,LockingPolicy,
0056     HolderSpecifier
0057   >                                   core;
0058   typedef typename core::handle_type  handle_type;
0059   typedef typename core::entry_type   entry_type;
0060   
0061 public:
0062   static const entry_type& entry(const handle_type& h)
0063   {
0064     return core::entry(h);
0065   }
0066 
0067   template<typename Checker>
0068   static void erase(const handle_type& h,Checker chk)
0069   {
0070     typedef typename core::lock_type lock_type;
0071     core::init();
0072     lock_type lock(core::mutex());(void)lock;
0073     if(chk(h))core::factory().erase(h);
0074   }
0075 };
0076 
0077 /* ADL-based customization point for factories providing the undocumented
0078  * insert_and_visit facility rather than regular insert. Default behavior is
0079  * to erase the entry if visitation throws.
0080  */
0081 
0082 template<typename Factory,typename Entry,typename F>
0083 typename Factory::handle_type
0084 insert_and_visit(Factory& fac,const Entry& x,F f)
0085 {
0086   typedef typename Factory::handle_type handle_type;
0087 
0088   handle_type h(fac.insert(x));
0089   BOOST_TRY{
0090     f(fac.entry(h));
0091   }
0092   BOOST_CATCH(...){
0093     fac().erase(h);
0094     BOOST_RETHROW;
0095   }
0096   BOOST_CATCH_END
0097   return h;
0098 }
0099 
0100 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0101 template<typename Factory,typename Entry,typename F>
0102 typename Factory::handle_type
0103 insert_and_visit(Factory& fac,Entry&& x,F f)
0104 {
0105   typedef typename Factory::handle_type handle_type;
0106 
0107   handle_type h(fac.insert(std::forward<Entry>(x)));
0108   BOOST_TRY{
0109     f(fac.entry(h));
0110   }
0111   BOOST_CATCH(...){
0112     fac.erase(h);
0113     BOOST_RETHROW;
0114   }
0115   BOOST_CATCH_END
0116   return h;
0117 }
0118 #endif
0119 
0120 template<
0121   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0122   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0123 >
0124 class flyweight_core
0125 {
0126 public:
0127   typedef typename ValuePolicy::key_type     key_type;
0128   typedef typename ValuePolicy::value_type   value_type;
0129   typedef typename ValuePolicy::rep_type     rep_type;
0130   typedef typename mpl::apply2<
0131     typename TrackingPolicy::entry_type,
0132     rep_type,
0133     key_type
0134   >::type                                    entry_type;
0135   typedef typename mpl::apply2<
0136     FactorySpecifier,
0137     entry_type,
0138     key_type
0139   >::type                                    factory_type;
0140   typedef typename factory_type::handle_type base_handle_type;
0141   typedef typename mpl::apply2<
0142     typename TrackingPolicy::handle_type,
0143     base_handle_type,
0144     flyweight_core_tracking_helper<
0145       ValuePolicy,Tag,TrackingPolicy,
0146       FactorySpecifier,LockingPolicy,
0147       HolderSpecifier
0148     >
0149   >::type                                    handle_type;
0150   typedef typename LockingPolicy::mutex_type mutex_type;
0151   typedef typename LockingPolicy::lock_type  lock_type;
0152 
0153   static bool init()
0154   {
0155     if(static_initializer)return true;
0156     else{
0157       holder_arg& a=holder_type::get();
0158       static_factory_ptr=&a.factory;
0159       static_mutex_ptr=&a.mutex;
0160       static_initializer=(static_factory_ptr!=0);
0161       return static_initializer;
0162     }
0163   }
0164 
0165   /* insert overloads*/
0166 
0167 #define BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY(args)         \
0168 {                                                             \
0169   return insert_rep(rep_type(BOOST_FLYWEIGHT_FORWARD(args))); \
0170 }
0171 
0172   BOOST_FLYWEIGHT_PERFECT_FWD(
0173     static handle_type insert,
0174     BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY)
0175 
0176 #undef BOOST_FLYWEIGHT_PERFECT_FWD_INSERT_BODY
0177 
0178   static handle_type insert(const value_type& x){return insert_value(x);}
0179   static handle_type insert(value_type& x){return insert_value(x);}
0180 
0181 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0182   static handle_type insert(const value_type&& x){return insert_value(x);}
0183   static handle_type insert(value_type&& x){return insert_value(std::move(x));}
0184 #endif
0185 
0186   static const entry_type& entry(const base_handle_type& h)
0187   {
0188     return factory().entry(h);
0189   }
0190 
0191   static const value_type& value(const handle_type& h)
0192   {
0193     return static_cast<const rep_type&>(entry(h));
0194   }
0195 
0196   static const key_type& key(const handle_type& h)
0197   BOOST_NOEXCEPT_IF(noexcept(
0198     static_cast<const rep_type&>(boost::declval<const entry_type&>())))
0199   {
0200     return static_cast<const rep_type&>(entry(h));
0201   }
0202 
0203   static factory_type& factory()
0204   {
0205     return *static_factory_ptr;
0206   }
0207 
0208   static mutex_type& mutex()
0209   {
0210     return *static_mutex_ptr;
0211   }
0212 
0213 private:
0214   struct                              holder_arg
0215   {
0216     factory_type factory;
0217     mutex_type   mutex;
0218   };
0219   typedef typename mpl::apply1<
0220     HolderSpecifier,
0221     holder_arg
0222   >::type                             holder_type;
0223 
0224   /* [key|copy|move]_construct_value: poor-man's pre-C++11 lambdas */
0225 
0226   struct key_construct_value
0227   {
0228     void operator()(const entry_type& e)const
0229     {
0230       ValuePolicy::key_construct_value(static_cast<const rep_type&>(e));
0231     }
0232   };
0233 
0234   struct copy_construct_value
0235   {
0236     copy_construct_value(const value_type& x_):x(x_){}
0237 
0238     void operator()(const entry_type& e)const
0239     {
0240       ValuePolicy::copy_construct_value(static_cast<const rep_type&>(e),x);
0241     }
0242 
0243     const value_type& x;
0244   };
0245 
0246 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0247   struct move_construct_value
0248   {
0249     move_construct_value(value_type&& x_):x(x_){}
0250 
0251     void operator()(const entry_type& e)const
0252     {
0253       ValuePolicy::move_construct_value(
0254         static_cast<const rep_type&>(e),std::move(x));
0255     }
0256 
0257     value_type& x;
0258   };
0259 #endif
0260 
0261   static handle_type insert_rep(const rep_type& x)
0262   {
0263     init();
0264     entry_type       e(x);
0265     lock_type        lock(mutex());(void)lock;
0266 
0267 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0268     return static_cast<handle_type>(
0269       insert_and_visit(factory(),std::move(e),key_construct_value()));
0270 #else
0271     return static_cast<handle_type>(
0272       insert_and_visit(factory(),e,key_construct_value()));
0273 #endif
0274   }
0275 
0276   static handle_type insert_value(const value_type& x)
0277   {
0278     init();
0279     entry_type       e((rep_type(x)));
0280     lock_type        lock(mutex());(void)lock;
0281 
0282 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0283     return static_cast<handle_type>(
0284       insert_and_visit(factory(),std::move(e),copy_construct_value(x)));
0285 #else
0286     return static_cast<handle_type>(
0287       insert_and_visit(factory(),e,copy_construct_value(x)));
0288 #endif
0289   }
0290 
0291 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0292   static handle_type insert_rep(rep_type&& x)
0293   {
0294     init();
0295     entry_type       e(std::move(x));
0296     lock_type        lock(mutex());(void)lock;
0297 
0298     return static_cast<handle_type>(
0299       insert_and_visit(factory(),std::move(e),key_construct_value()));
0300   }
0301 
0302   static handle_type insert_value(value_type&& x)
0303   {
0304     init();
0305     entry_type       e(rep_type(std::move(x)));
0306     lock_type        lock(mutex());(void)lock;
0307 
0308     return static_cast<handle_type>(
0309       insert_and_visit(
0310         factory(),std::move(e),move_construct_value(std::move(x))));
0311   }
0312 #endif
0313 
0314   static bool          static_initializer;
0315   static factory_type* static_factory_ptr;
0316   static mutex_type*   static_mutex_ptr;
0317 };
0318 
0319 template<
0320   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0321   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0322 >
0323 bool
0324 flyweight_core<
0325   ValuePolicy,Tag,TrackingPolicy,
0326   FactorySpecifier,LockingPolicy,HolderSpecifier>::static_initializer=
0327   flyweight_core<
0328       ValuePolicy,Tag,TrackingPolicy,
0329       FactorySpecifier,LockingPolicy,HolderSpecifier>::init();
0330 
0331 template<
0332   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0333   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0334 >
0335 typename flyweight_core<
0336   ValuePolicy,Tag,TrackingPolicy,
0337   FactorySpecifier,LockingPolicy,HolderSpecifier>::factory_type*
0338 flyweight_core<
0339   ValuePolicy,Tag,TrackingPolicy,
0340   FactorySpecifier,LockingPolicy,HolderSpecifier>::static_factory_ptr=0;
0341 
0342 template<
0343   typename ValuePolicy,typename Tag,typename TrackingPolicy,
0344   typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier
0345 >
0346 typename flyweight_core<
0347   ValuePolicy,Tag,TrackingPolicy,
0348   FactorySpecifier,LockingPolicy,HolderSpecifier>::mutex_type*
0349 flyweight_core<
0350   ValuePolicy,Tag,TrackingPolicy,
0351   FactorySpecifier,LockingPolicy,HolderSpecifier>::static_mutex_ptr=0;
0352 
0353 } /* namespace flyweights::detail */
0354 
0355 } /* namespace flyweights */
0356 
0357 } /* namespace boost */
0358 
0359 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
0360 #pragma warning(pop)
0361 #endif
0362 
0363 #endif