MACE  1.0.0
 All Classes Namespaces Files Functions Variables Enumerations Defines
libs/rpc/include/mace/rpc/json/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   #include <mace/rpc/json/client_base.hpp>
00016 
00017   namespace mace { namespace rpc { namespace json {
00022     template<typename MemberPtr>
00023     struct client_member;
00024 
00025     class client_base;
00026 
00027     namespace detail {
00028       namespace client_interface {
00029         template<typename VTableType>
00030         class set_visitor {
00031           public:
00032             set_visitor( VTableType& vt, mace::rpc::json::client_base* ci )
00033             :m_ci(ci),vtbl(vt){}
00034 
00035             template<typename M, M m>
00036             void operator()( const char* name )const {
00037               (vtbl.*m).set( name, m_ci );
00038             }
00039           private:
00040             mace::rpc::json::client_base* m_ci;
00041             VTableType&                    vtbl;
00042         };
00043 
00044         struct client_member_base {
00045           client_member_base():m_ci(0){}
00046           void set( const std::string& mid, mace::rpc::json::client_base* ci ) {
00047             m_method_id    = mid;
00048             m_ci           = ci;
00049           }
00050           protected:
00051             std::string                    m_method_id;
00052             mace::rpc::json::client_base* m_ci;
00053         };
00054       }
00055     }
00056     
00069     struct client_interface {
00075       template<typename MemberPointer>
00076       struct calculate_type {
00077         typedef client_member<MemberPointer>  type; 
00078       };
00079 
00080       template<typename ClientType>
00081       static void set( ClientType& cl ) {
00082         mace::stub::visit( cl, detail::client_interface::set_visitor<typename ClientType::vtable_type>( *cl, &cl ) );
00083       }
00084     };
00085 
00086 
00087   #define PARAM_NAME(z,n,type)         BOOST_PP_CAT(a,n)
00088   #define PARAM_TYPE_NAME(z,n,type)   BOOST_PP_CAT(typename A,n)
00089   #define PARAM_TYPE(z,n,type)   BOOST_PP_CAT(A,n)
00090   #define PARAM_ARG(z,n,type)     PARAM_TYPE(z,n,type) PARAM_NAME(z,n,type)
00091 
00092 #        ifndef BOOST_CLIENT_IMPL_SIZE
00093 #           define BOOST_CLIENT_IMPL_SIZE 8
00094 #        endif
00095 
00096 #       include <boost/preprocessor/iteration/iterate.hpp>
00097 #       define BOOST_PP_ITERATION_LIMITS (0, BOOST_CLIENT_IMPL_SIZE -1 )
00098 #       define BOOST_PP_FILENAME_1 <mace/rpc/json/client_interface.hpp>
00099 #       include BOOST_PP_ITERATE()
00100 
00101   #undef PARAM_NAME
00102   #undef PARAM_TYPE
00103   #undef PARAM_ARG
00104 
00105   } } } // namespace mace::rpc::json
00106   #endif // BOOST_CLIENT_INTERFACE_HPP
00107 
00108 #else // BOOST_PP_IS_ITERATING
00109 
00110 #define n BOOST_PP_ITERATION()
00111 #define PARAM_NAMES          BOOST_PP_ENUM(n,PARAM_NAME,A) // name_N
00112 #define PARAM_ARGS           BOOST_PP_ENUM(n,PARAM_ARG,A) // TYPE_N name_N
00113 #define PARAM_TYPE_NAMES     BOOST_PP_ENUM(n,PARAM_TYPE_NAME,A) // typename TYPE_N
00114 #define PARAM_TYPES          BOOST_PP_ENUM(n,PARAM_TYPE,A) // TYPE_N
00115 
00116 template<typename R, typename Class BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES>
00117 struct client_member<R(Class::*)(PARAM_TYPES)const> : public detail::client_interface::client_member_base
00118 {
00119   typedef typename mace::stub::adapt_void<R>::result_type    result_type;
00120   typedef mace::cmt::future<result_type>                        future_type;
00121   typedef client_member                                          self_type;
00122   typedef boost::fusion::vector<PARAM_TYPES>                     fused_params;
00123   typedef boost::function_traits<result_type(PARAM_TYPES)>       traits;
00124   static const bool                                              is_const = true;
00125 
00126   typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type   signature;
00127 
00128   inline future_type operator()( PARAM_ARGS )const {
00129     return (*this)( boost::fusion::make_vector(PARAM_NAMES) );
00130   }
00131   inline future_type operator() ( const fused_params& fp )const {
00132     BOOST_ASSERT(m_ci);
00133     return m_ci->call_fused<result_type,fused_params>( m_method_id, fp );
00134   }
00135   inline void notice( const fused_params& fp )const {
00136     BOOST_ASSERT(m_ci);
00137     return m_ci->notice_fused( m_method_id, fp );
00138   }
00139 };
00140 
00141 template<typename R, typename Class  BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES>
00142 struct client_member<R(Class::*)(PARAM_TYPES)>  : public detail::client_interface::client_member_base
00143 {
00144   typedef typename mace::stub::adapt_void<R>::result_type   result_type;
00145   typedef mace::cmt::future<result_type>                       future_type;
00146   typedef client_member                                         self_type;
00147   typedef boost::fusion::vector<PARAM_TYPES>                    fused_params;
00148   typedef boost::function_traits<result_type(PARAM_TYPES)>      traits;
00149   typedef boost::function<result_type(const fused_params&)>     delegate_type;
00150   static const bool                                             is_const  = false;
00151 
00152   // boost::result_of
00153   typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type signature;
00154 
00155   inline future_type operator()( PARAM_ARGS ) {
00156     return (*this)( boost::fusion::make_vector(PARAM_NAMES) );
00157   }
00158   inline future_type operator() ( const fused_params& fp ) {
00159     BOOST_ASSERT(m_ci);
00160     return m_ci->call_fused<result_type,fused_params>( m_method_id, fp );
00161   }
00162   inline void notice( const fused_params& fp )const {
00163     BOOST_ASSERT(m_ci);
00164     return m_ci->notice_fused( m_method_id, fp );
00165   }
00166 
00167 };
00168 
00169 
00170 #undef n
00171 #undef PARAM_NAMES         
00172 #undef PARAM_ARGS        
00173 #undef PARAM_TYPE_NAMES 
00174 #undef PARAM_TYPES     
00175 
00176 #endif // BOOST_PP_IS_ITERATING