| /* Copyright 2006-2009 Joaquin M Lopez Munoz. |
| * Distributed under the Boost Software License, Version 1.0. |
| * (See accompanying file LICENSE_1_0.txt or copy at |
| * http://www.boost.org/LICENSE_1_0.txt) |
| * |
| * See http://www.boost.org/libs/flyweight for library home page. |
| */ |
| |
| #ifndef BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP |
| #define BOOST_FLYWEIGHT_DETAIL_FLYWEIGHT_CORE_HPP |
| |
| #if defined(_MSC_VER)&&(_MSC_VER>=1200) |
| #pragma once |
| #endif |
| |
| #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
| #include <boost/detail/no_exceptions_support.hpp> |
| #include <boost/detail/workaround.hpp> |
| #include <boost/mpl/apply.hpp> |
| #include <boost/preprocessor/repetition/enum_params.hpp> |
| |
| #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) |
| #pragma warning(push) |
| #pragma warning(disable:4101) /* unreferenced local vars */ |
| #endif |
| |
| /* flyweight_core provides the inner implementation of flyweight<> by |
| * weaving together a value policy, a flyweight factory, a holder for the |
| * factory,a tracking policy and a locking policy. |
| */ |
| |
| namespace boost{ |
| |
| namespace flyweights{ |
| |
| namespace detail{ |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| class flyweight_core; |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| struct flyweight_core_tracking_helper |
| { |
| private: |
| typedef flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy, |
| HolderSpecifier |
| > core; |
| typedef typename core::handle_type handle_type; |
| typedef typename core::entry_type entry_type; |
| |
| public: |
| static const entry_type& entry(const handle_type& h) |
| { |
| return core::entry(h); |
| } |
| |
| template<typename Checker> |
| static void erase(const handle_type& h,Checker check) |
| { |
| typedef typename core::lock_type lock_type; |
| lock_type lock(core::mutex()); |
| if(check(h))core::factory().erase(h); |
| } |
| }; |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| class flyweight_core |
| { |
| public: |
| typedef typename ValuePolicy::key_type key_type; |
| typedef typename ValuePolicy::value_type value_type; |
| typedef typename ValuePolicy::rep_type rep_type; |
| typedef typename mpl::apply2< |
| typename TrackingPolicy::entry_type, |
| rep_type, |
| key_type |
| >::type entry_type; |
| typedef typename mpl::apply2< |
| FactorySpecifier, |
| entry_type, |
| key_type |
| >::type factory_type; |
| typedef typename factory_type::handle_type base_handle_type; |
| typedef typename mpl::apply2< |
| typename TrackingPolicy::handle_type, |
| base_handle_type, |
| flyweight_core_tracking_helper< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy, |
| HolderSpecifier |
| > |
| >::type handle_type; |
| typedef typename LockingPolicy::mutex_type mutex_type; |
| typedef typename LockingPolicy::lock_type lock_type; |
| |
| static bool init() |
| { |
| if(static_initializer)return true; |
| else{ |
| holder_arg& a=holder_type::get(); |
| static_factory_ptr=&a.factory; |
| static_mutex_ptr=&a.mutex; |
| static_initializer=(static_factory_ptr!=0); |
| return static_initializer; |
| } |
| } |
| |
| /* insert overloads*/ |
| |
| #define BOOST_FLYWEIGHT_PERFECT_FWD_NAME static handle_type insert |
| #define BOOST_FLYWEIGHT_PERFECT_FWD_BODY(n) \ |
| { \ |
| return insert_rep(rep_type(BOOST_PP_ENUM_PARAMS(n,t))); \ |
| } |
| #include <boost/flyweight/detail/perfect_fwd.hpp> |
| |
| static handle_type insert(const value_type& x){return insert_value(x);} |
| static handle_type insert(value_type& x){return insert_value(x);} |
| |
| static const entry_type& entry(const base_handle_type& h) |
| { |
| return factory().entry(h); |
| } |
| |
| static const value_type& value(const handle_type& h) |
| { |
| return static_cast<const rep_type&>(entry(h)); |
| } |
| |
| static const key_type& key(const handle_type& h) |
| { |
| return static_cast<const rep_type&>(entry(h)); |
| } |
| |
| static factory_type& factory() |
| { |
| return *static_factory_ptr; |
| } |
| |
| static mutex_type& mutex() |
| { |
| return *static_mutex_ptr; |
| } |
| |
| private: |
| struct holder_arg |
| { |
| factory_type factory; |
| mutex_type mutex; |
| }; |
| typedef typename mpl::apply1< |
| HolderSpecifier, |
| holder_arg |
| >::type holder_type; |
| |
| static handle_type insert_rep(const rep_type& x) |
| { |
| init(); |
| entry_type e(x); |
| lock_type lock(mutex()); |
| base_handle_type h(factory().insert(e)); |
| BOOST_TRY{ |
| ValuePolicy::construct_value( |
| static_cast<const rep_type&>(entry(h))); |
| } |
| BOOST_CATCH(...){ |
| factory().erase(h); |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| return static_cast<handle_type>(h); |
| } |
| |
| static handle_type insert_value(const value_type& x) |
| { |
| init(); |
| entry_type e((rep_type(x))); |
| lock_type lock(mutex()); |
| base_handle_type h(factory().insert(e)); |
| BOOST_TRY{ |
| ValuePolicy::copy_value( |
| static_cast<const rep_type&>(entry(h))); |
| } |
| BOOST_CATCH(...){ |
| factory().erase(h); |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| return static_cast<handle_type>(h); |
| } |
| |
| static bool static_initializer; |
| static factory_type* static_factory_ptr; |
| static mutex_type* static_mutex_ptr; |
| }; |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| bool |
| flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::static_initializer= |
| flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::init(); |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| typename flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::factory_type* |
| flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::static_factory_ptr=0; |
| |
| template< |
| typename ValuePolicy,typename Tag,typename TrackingPolicy, |
| typename FactorySpecifier,typename LockingPolicy,typename HolderSpecifier |
| > |
| typename flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::mutex_type* |
| flyweight_core< |
| ValuePolicy,Tag,TrackingPolicy, |
| FactorySpecifier,LockingPolicy,HolderSpecifier>::static_mutex_ptr=0; |
| |
| } /* namespace flyweights::detail */ |
| |
| } /* namespace flyweights */ |
| |
| } /* namespace boost */ |
| |
| #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) |
| #pragma warning(pop) |
| #endif |
| |
| #endif |