boost/flyweight/detail/flyweight_core.hpp
/* Copyright 2006-2008 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/flyweight/detail/handle_factory_adaptor.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 base_factory_type;
typedef typename mpl::apply2<
typename TrackingPolicy::handle_type,
typename base_factory_type::handle_type,
flyweight_core_tracking_helper<
ValuePolicy,Tag,TrackingPolicy,
FactorySpecifier,LockingPolicy,
HolderSpecifier
>
>::type handle_type;
typedef handle_factory_adaptor<
base_factory_type,
handle_type,entry_type
> factory_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 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());
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 h;
}
static handle_type insert_value(const value_type& x)
{
init();
entry_type e=entry_type(rep_type(x));
lock_type lock(mutex());
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 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