Bytemaster's Boost Libraries
|
00001 #ifndef BOOST_PP_IS_ITERATING 00002 #ifndef BOOST_RPC_MIRROR_INTERFACE_HPP 00003 #define BOOST_RPC_MIRROR_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 <boost/reflect/void.hpp> 00013 #include <boost/signals.hpp> 00014 #include <boost/reflect/vtable.hpp> 00015 00016 namespace boost { namespace rpc { 00021 template<typename MemberPtr> 00022 struct mirror_member; 00023 00044 struct mirror_interface 00045 { 00051 template<typename MemberPointer> 00052 struct calculate_type { 00053 typedef mirror_member<MemberPointer> type; 00054 }; 00055 00056 #ifndef DOXYGEN 00057 template<typename T, typename VTableType> 00058 class set_visitor { 00059 public: 00060 set_visitor( VTableType& vt, T& self ) 00061 :m_self(self),vtable(vt){} 00062 00063 template<typename InterfaceName, typename M> 00064 void operator()( M InterfaceName::* m, const char* name )const { 00065 assign<M> a(m_self,vtable.*m); 00066 M::template get_member_ptr<T>( a ); 00067 } 00068 private: 00069 template<typename Member> 00070 struct assign { 00071 assign( T& _v, Member& _m ):v(_v),m(_m){} 00072 00073 template<typename MemberPtr> 00074 void operator=( const MemberPtr& p ) { 00075 m.set_delegate( &v, p ); 00076 } 00077 private: 00078 T& v; 00079 Member& m; 00080 }; 00081 T& m_self; 00082 VTableType& vtable; 00083 }; 00084 #endif 00085 template<typename T, typename VTableType> 00086 static void set_vtable( VTableType& vtable, T& value ) { 00087 boost::reflect::vtable_reflector<typename VTableType::interface_type>::visit( &vtable, 00088 set_visitor<T,VTableType>(vtable,value) ); 00089 } 00090 template<typename T, typename VTableType> 00091 static void set_vtable( VTableType& vtable, const T& value ) { 00092 boost::reflect::vtable_reflector<typename VTableType::interface_type>::visit( &vtable, 00093 set_visitor<T,VTableType>(vtable,value) ); 00094 } 00095 }; 00096 00097 #ifndef DOXYGEN 00098 00104 struct scoped_block_signal { 00105 scoped_block_signal( boost::signals::connection& _c ) 00106 :c(_c),unblock(false){ 00107 if( c != boost::signals::connection() && !c.blocked() ) { 00108 unblock = true; 00109 c.block(); 00110 } 00111 } 00112 ~scoped_block_signal() { 00113 if( unblock && c != boost::signals::connection() ) 00114 c.unblock(); 00115 } 00116 private: 00117 bool unblock; 00118 boost::signals::connection& c; 00119 }; 00120 #endif 00121 00122 00123 #define PARAM_NAME(z,n,type) BOOST_PP_CAT(a,n) 00124 #define PARAM_PLACE_HOLDER(z,n,type) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1) ) 00125 #define PARAM_TYPE_NAME(z,n,type) BOOST_PP_CAT(typename A,n) 00126 #define PARAM_TYPE(z,n,type) BOOST_PP_CAT(A,n) 00127 #define PARAM_ARG(z,n,type) PARAM_TYPE(z,n,type) PARAM_NAME(z,n,type) 00128 00129 # ifndef BOOST_RPC_IMPL_SIZE 00130 # define BOOST_RPC_IMPL_SIZE 8 00131 # endif 00132 00133 # include <boost/preprocessor/iteration/iterate.hpp> 00134 # define BOOST_PP_ITERATION_LIMITS (0, BOOST_RPC_IMPL_SIZE -1 ) 00135 # define BOOST_PP_FILENAME_1 <boost/rpc/mirror_interface.hpp> 00136 # include BOOST_PP_ITERATE() 00137 00138 #undef PARAM_NAME 00139 #undef PARAM_TYPE 00140 #undef PARAM_ARG 00141 00142 } } // namespace boost::reflect 00143 #endif // BOOST_RPC_MIRROR_INTERFACE_HPP 00144 00145 #else // BOOST_PP_IS_ITERATING 00146 00147 #define n BOOST_PP_ITERATION() 00148 #define PARAM_NAMES BOOST_PP_ENUM(n,PARAM_NAME,A) // name_N 00149 #define PARAM_PLACE_HOLDERS BOOST_PP_ENUM_TRAILING(n,PARAM_PLACE_HOLDER,A) // _(N+1) 00150 #define PARAM_ARGS BOOST_PP_ENUM(n,PARAM_ARG,A) // TYPE_N name_N 00151 #define PARAM_TYPE_NAMES BOOST_PP_ENUM(n,PARAM_TYPE_NAME,A) // typename TYPE_N 00152 #define PARAM_TYPES BOOST_PP_ENUM(n,PARAM_TYPE,A) // TYPE_N 00153 00154 template<typename R, typename Class BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES> 00155 struct mirror_member<R(Class::*)(PARAM_TYPES)const> { 00156 typedef boost::cmt::future<R> result_type; 00157 typedef mirror_member self_type; 00158 typedef boost::fusion::vector<PARAM_TYPES> fused_params; 00159 typedef boost::function_traits<result_type(PARAM_TYPES)> traits; 00160 static const bool is_const = true; 00161 static const bool is_signal = false; 00162 typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type signature; 00163 00164 result_type operator()( PARAM_ARGS )const { 00165 return m_delegate( fused_params(PARAM_NAMES) ); 00166 } 00167 result_type operator() ( const fused_params& fp )const { 00168 return m_delegate( fp ); 00169 } 00170 mirror_member& operator=( const mirror_member& d ) { 00171 m_delegate = d.m_delegate; 00172 return *this; 00173 } 00174 template<typename T> 00175 mirror_member& operator=( const T& d ) { 00176 m_delegate = d; 00177 return *this; 00178 } 00179 private: 00180 boost::function<result_type(const fused_params&)> m_delegate; 00181 }; 00182 00183 template<typename R, typename Class BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES> 00184 struct mirror_member<R(Class::*)(PARAM_TYPES)> { 00185 typedef boost::cmt::future<R> result_type; 00186 typedef mirror_member self_type; 00187 typedef boost::fusion::vector<PARAM_TYPES> fused_params; 00188 typedef boost::function_traits<R(PARAM_TYPES)> traits; 00189 typedef boost::function<result_type(const fused_params&)> delegate_type; 00190 static const bool is_const = false; 00191 static const bool is_signal = false; 00192 typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type signature; 00193 00194 result_type operator()( PARAM_ARGS ) { 00195 return m_delegate( fused_params(PARAM_NAMES) ); 00196 } 00197 result_type operator() ( const fused_params& fp ) { 00198 return m_delegate( fp ); 00199 } 00200 mirror_member& operator=( const mirror_member& d ) { 00201 m_delegate = d.m_delegate; 00202 return *this; 00203 } 00204 template<typename T> 00205 mirror_member& operator=( const T& d ) { 00206 m_delegate = d; 00207 return *this; 00208 } 00209 private: 00210 delegate_type m_delegate; 00211 }; 00212 00213 00214 template<typename R, typename Class BOOST_PP_COMMA_IF(n) PARAM_TYPE_NAMES> 00215 struct mirror_member< boost::signal<R(PARAM_TYPES)> (Class::*) > 00216 { 00217 typedef boost::cmt::future<typename boost::reflect::adapt_void<R>::result_type> result_type; 00218 typedef mirror_member self_type; 00219 typedef boost::fusion::vector<PARAM_TYPES> fused_params; 00220 typedef boost::function_traits<result_type(PARAM_TYPES)> traits; 00221 typedef boost::signal<R(PARAM_TYPES)> signal_type; 00222 static const bool is_const = false; 00223 static const bool is_signal = true; 00224 00225 // boost::result_of 00226 typedef typename boost::remove_pointer<result_type(*)(PARAM_TYPES)>::type signature; 00227 00228 result_type operator()( PARAM_ARGS ) { 00229 return (*this)( fused_params(PARAM_NAMES) ); 00230 } 00231 00232 result_type operator() ( const fused_params& fp ) { 00233 scoped_block_signal block_reverse(m_reverse_con); 00234 if( int(m_signal.num_slots()) - 1 > 0 ) // do not count our reverse connection 00235 boost::fusion::make_fused_function_object( boost::ref(m_signal) )(fp); 00236 return m_delegate( fp ); 00237 } 00238 00239 // emits locally, but does not forward to delegate 00240 typename boost::reflect::adapt_void<R>::result_type emit( const fused_params& fp ) { 00241 scoped_block_signal block_reverse(m_reverse_con); 00242 return boost::reflect::adapt_void<R,boost::function<R(const fused_params&)> >( 00243 boost::fusion::make_fused_function_object( boost::ref(m_signal) ) )(fp); 00244 } 00245 00246 template<typename T> 00247 mirror_member& operator=( const T& d ) { 00248 m_delegate = d; 00249 /* 00250 m_signal.disconnect_all_slots(); 00251 m_reverse_con = 00252 d.connect( boost::fusion::make_unfused( 00253 boost::bind( &mirror_member::emit, this, _1) ) ); 00254 m_delegate = emit_or_throw(boost::reflect::adapt_void<R,T>(d)); 00255 */ 00256 return *this; 00257 } 00258 00259 template<typename Functor> 00260 boost::signals::connection connect( const Functor& f ) { 00261 boost::signals::connection c = m_signal.connect(boost::reflect::adapt_void<R,Functor>(f) ); 00262 if( m_connect_delegate ) 00263 m_connect_delegate(m_signal.num_slots()); 00264 return c; 00265 } 00266 void disconnect( const boost::signals::connection& c ) { 00267 c.disconnect(); 00268 if( m_connect_delegate ) 00269 m_connect_delegate(m_signal.num_slots()); 00270 } 00271 00272 void set_connect_delegate( const boost::function<void(int)>& f ) { 00273 m_connect_delegate = f; 00274 } 00275 00276 // sets the delegate that will be called when the signal is 'emited' 00277 template<typename C, typename M> 00278 void set_delegate( C* s, M m ) { 00279 m_signal.disconnect_all_slots(); 00280 m_reverse_con = 00281 (s->*m).connect( boost::fusion::make_unfused( 00282 boost::bind( &mirror_member::emit, this, _1) ) ); 00283 00284 m_delegate = emit_or_throw( s->*m ); 00285 } 00286 00287 ~mirror_member() { 00288 m_signal.disconnect_all_slots(); 00289 if( m_reverse_con != boost::signals::connection() ) 00290 m_reverse_con.disconnect(); 00291 } 00292 00293 private: 00294 00295 struct emit_or_throw { 00296 struct no_connected_slots : public std::exception, public boost::exception { 00297 const char* what()const throw() { return "no connected slots"; } 00298 }; 00299 00300 emit_or_throw( signal_type& s ):sig(s){} 00301 result_type operator()( const fused_params& p ) { 00302 if( int(sig.num_slots()) -1 > 0 ) { // do not count our reverse connection 00303 return boost::reflect::adapt_void<R, boost::function<R(const fused_params&)> >( 00304 boost::fusion::make_fused_function_object(boost::ref(sig)))(p); 00305 } 00306 BOOST_THROW_EXCEPTION( no_connected_slots() ); 00307 } 00308 signal_type& sig; 00309 }; 00310 00311 boost::function<void(int)> m_connect_delegate; 00312 boost::function<result_type(const fused_params&)> m_delegate; 00313 boost::signals::connection m_reverse_con; 00314 boost::signal<R(PARAM_TYPES)> m_signal; 00315 }; 00316 00317 #undef n 00318 #undef PARAM_NAMES 00319 #undef PARAM_PLACE_HOLDERS 00320 #undef PARAM_ARGS 00321 #undef PARAM_TYPE_NAMES 00322 #undef PARAM_TYPES 00323 00324 #endif // BOOST_PP_IS_ITERATING