MACE  1.0.0
 All Classes Namespaces Files Functions Variables Enumerations Defines
libs/rpc/include/mace/rpc/client_interface.hpp
00001 #ifndef BOOST_PP_IS_ITERATING
00002   #ifndef BOOST_CLIENT_INTERFACE_HPP
00003   #define BOOST_CLIENT_INTERFACE_HPP
00004   #include <boost/bind.hpp>
00005   #include <boost/preprocessor/repetition.hpp>
00006   #include <boost/preprocessor/seq/for_each.hpp>
00007 
00008   #include <boost/fusion/container/vector.hpp>
00009   #include <boost/fusion/container/generation/make_vector.hpp>
00010   #include <boost/fusion/functional/generation/make_fused_function_object.hpp>
00011   #include <boost/fusion/functional/generation/make_unfused.hpp>
00012   #include <mace/stub/void.hpp>
00013   #include <mace/stub/vtable.hpp>
00014 
00015   namespace mace { namespace rpc { 
00020     template<typename MemberPtr, typename ConnectionType>
00021     struct client_member;
00022 
00023     template<typename ConnectionType>
00024     struct client_member_base {
00025       client_member_base(){}
00026       void set( const std::string& mid, const typename ConnectionType::ptr& con ) {
00027         m_method_id    = mid;
00028         m_con          = con;
00029       }
00030       protected:
00031         std::string                      m_method_id;
00032         typename ConnectionType::ptr     m_con;
00033     };
00034     
00047     template<typename ConnectionType>
00048     struct client_interface {
00054       template<typename MemberPointer>
00055       struct calculate_type {
00056         typedef client_member<MemberPointer,ConnectionType>  type; 
00057       };
00058 
00059       template<typename ClientType>
00060       static void set_vtable( ClientType& cl, typename ConnectionType::ptr& t ) {
00061         mace::stub::visit( cl, set_visitor<typename ClientType::vtable_type>( *cl, t ) );
00062       }
00063 
00064       template<typename VTableType>
00065       class set_visitor {
00066         public:
00067           set_visitor( VTableType& vt, typename ConnectionType::ptr& con )
00068           :m_con(con),vtbl(vt){}
00069 
00070           template<typename M, M m>
00071           void operator()( const char* name )const {
00072             (vtbl.*m).set( name, m_con );
00073           }
00074         private:
00075           typename ConnectionType::ptr&  m_con;
00076           VTableType&                    vtbl;
00077       };
00078     };
00079 
00080 
00081   #define PARAM_NAME(z,n,type)         BOOST_PP_CAT(a,n)
00082   #define PARAM_TYPE_NAME(z,n,type)   BOOST_PP_CAT(typename A,n)
00083   #define PARAM_TYPE(z,n,type)   BOOST_PP_CAT(A,n)
00084   #define PARAM_ARG(z,n,type)     PARAM_TYPE(z,n,type) PARAM_NAME(z,n,type)
00085 
00086 #        ifndef BOOST_CLIENT_IMPL_SIZE
00087 #           define BOOST_CLIENT_IMPL_SIZE 8
00088 #        endif
00089 
00090 #       include <boost/preprocessor/iteration/iterate.hpp>
00091 #       define BOOST_PP_ITERATION_LIMITS (0, BOOST_CLIENT_IMPL_SIZE -1 )
00092 #       define BOOST_PP_FILENAME_1 <mace/rpc/client_interface.hpp>
00093 #       include BOOST_PP_ITERATE()
00094 
00095   #undef PARAM_NAME
00096   #undef PARAM_TYPE
00097   #undef PARAM_ARG
00098 
00099    } } // namespace mace::rpc
00100   #endif // BOOST_CLIENT_INTERFACE_HPP
00101 
00102 #else // BOOST_PP_IS_ITERATING
00103 
00104 #define n BOOST_PP_ITERATION()
00105 #define PARAM_NAMES          BOOST_PP_ENUM(n,PARAM_NAME,A) // name_N
00106 #define PARAM_ARGS           BOOST_PP_ENUM(n,PARAM_ARG,A) // TYPE_N name_N
00107 #define PARAM_TYPE_NAMES     BOOST_PP_ENUM(n,PARAM_TYPE_NAME,A) // typename TYPE_N
00108 #define PARAM_TYPES          BOOST_PP_ENUM(n,PARAM_TYPE,A) // TYPE_N
00109 
00110 template<typename ConnectionType, typename R, typename Class BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES>
00111 struct client_member<R(Class::*)(PARAM_TYPES)const,ConnectionType> : public client_member_base<ConnectionType> {
00112   typedef typename mace::stub::adapt_void<R>::result_type    result_type;
00113   typedef mace::cmt::future<result_type>                        future_type;
00114   typedef client_member                                          self_type;
00115   typedef boost::fusion::vector<PARAM_TYPES>                     fused_params;
00116   typedef boost::function_traits<result_type(PARAM_TYPES)>       traits;
00117   static const bool                                              is_const = true;
00118 
00119   typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type   signature;
00120 
00121   inline future_type operator()( PARAM_ARGS )const {
00122     return (*this)( boost::fusion::make_vector(PARAM_NAMES) );
00123   }
00124   inline future_type operator() ( const fused_params& fp )const {
00125     BOOST_ASSERT(this->m_con);
00126     return this->m_con->template call_fused<result_type,fused_params>( std::string(this->m_method_id), fp );
00127   }
00128   inline future_type operator() ( fused_params&& fp )const {
00129     BOOST_ASSERT(this->m_con);
00130     return this->m_con->template call_fused<result_type,fused_params>( std::string(this->m_method_id), std::move(fp) );
00131   }
00132   inline void notice( PARAM_ARGS )const {
00133     notice( boost::fusion::make_vector(PARAM_NAMES) );
00134   }
00135   inline void notice( const fused_params& fp )const {
00136     BOOST_ASSERT(this->m_con);
00137     this->m_con->notice_fused( this->m_method_id, fp );
00138   }
00139 };
00140 
00141 template<typename ConnectionType, typename R, typename Class  BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES>
00142 struct client_member<R(Class::*)(PARAM_TYPES),ConnectionType>  : public client_member_base<ConnectionType> {
00143   typedef typename mace::stub::adapt_void<R>::result_type   result_type;
00144   typedef mace::cmt::future<result_type>                       future_type;
00145   typedef client_member                                         self_type;
00146   typedef boost::fusion::vector<PARAM_TYPES>                    fused_params;
00147   typedef boost::function_traits<result_type(PARAM_TYPES)>      traits;
00148   typedef boost::function<result_type(const fused_params&)>     delegate_type;
00149   static const bool                                             is_const  = false;
00150 
00151   // boost::result_of
00152   typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type signature;
00153 
00154   inline future_type operator()( PARAM_ARGS ) {
00155     return (*this)( boost::fusion::make_vector(PARAM_NAMES) );
00156   }
00157   inline future_type operator() ( const fused_params& fp ) {
00158     BOOST_ASSERT(this->m_con);
00159     return this->m_con->template call_fused<result_type,fused_params>( this->m_method_id, fp );
00160   }
00161 
00162   inline future_type operator() ( fused_params&& fp ) {
00163     BOOST_ASSERT(this->m_con);
00164     return this->m_con->template call_fused<result_type,fused_params>( std::string(this->m_method_id), std::move(fp) );
00165   }
00166 
00167   inline void notice( PARAM_ARGS )const {
00168     return notice( boost::fusion::make_vector(PARAM_NAMES) );
00169   }
00170   inline void notice( const fused_params& fp )const {
00171     BOOST_ASSERT(this->m_con);
00172     this->m_con->notice_fused( this->m_method_id, fp );
00173   }
00174 };
00175 
00176 
00177 #undef n
00178 #undef PARAM_NAMES         
00179 #undef PARAM_ARGS        
00180 #undef PARAM_TYPE_NAMES 
00181 #undef PARAM_TYPES     
00182 
00183 #endif // BOOST_PP_IS_ITERATING