MACE
1.0.0
|
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