C++模板类型匹配在RPC分发中的应用研究
C++模板类型匹配在RPC分发中的应用研究
最近研究了一下MammothServer,发现里面有一个叫Dispatcher的实现,很有意思。正好自己最近在学习boost::mpl等东东,因此花了几天学习,并把自己的学习心得总结了一下。相信对大多数C++程序员会有帮助。前言
在编写通讯框架时,经常要处理众多的协议。而处理完协议后,再调用相应的处理函数时,
在C++中,我们一般要使用统一接口。比如Windows消息中的MSG结构等等。
这种统一的处理结构最大的缺点是缺乏有效地类型检测,容易出错。因为,编译器无法对每一个特定消息进行数据合法性检查。
不过利用模板技术,完全可以实现RPC参数的解析以及与C++函数的自动匹配,支持不定长参数。
伪代码
C++代码
- class Dispatcher {
- map<string, func> invokers_;
- void register_function( const std::string& name, func);
- void invoke( void* packet ) {
- sequence params = deserialize( packet );
- invokers_[ params["name"] ]( params );
- }
- }
- void hello(const std::string& msg ) {
- }
- void hello2(const std::string& msg , const std::string& from) {
- }
- Dispatcher.register_function("hello", hello );
- Dispatcher.register_function("hello2", hello2 );
class Dispatcher { map<string, func> invokers_; void register_function( const std::string& name, func); void invoke( void* packet ) { sequence params = deserialize( packet ); invokers_[ params["name"] ]( params ); } } void hello(const std::string& msg ) { } void hello2(const std::string& msg , const std::string& from) { } Dispatcher.register_function("hello", hello ); Dispatcher.register_function("hello2", hello2 );
准备知识
C++ template
boost::bind
boost::function 仿函数
boost::fusion 处理不同类型参数的sequence
boost::mpl 处理函数参数表的推导
part1 - basic framework
由于用户提供的函数带有不确定个数的参数,因此,在dispatcher内部,需要首先将用户提供的Function转换成为统一参数的仿函数,定义如下:
引用 出于讲解的需要,暂时不支持返回值,且与应用相关的参数被简化为一个void*
C++代码
- typedef boost::function<void(void*)> invoker_function_type;
typedef boost::function<void(void*)> invoker_function_type;
相应的容器为
C++代码
- typedef std::map<std::string, invoker_function_type> dictionary_type;
typedef std::map<std::string, invoker_function_type> dictionary_type;
注册函数考虑面向对象,因此包含函数Function和类实例Base.
C++代码
- class Dispatcher {
- // 实际的invoke函数形式
- typedef boost::function<void(void*)> invoker_function_type;
- // name -> invoker 表
- typedef std::map<std::string, invoker_function_type> dictionary_type;
- dictionary_type m_invokers;
- public:
- template<typename Function, typename Base>
- void register_function(std::string const & name, Function f, Base& base) {
- m_invokers[name] = ...; //TODO
- }
- };
class Dispatcher { // 实际的invoke函数形式 typedef boost::function<void(void*)> invoker_function_type; // name -> invoker 表 typedef std::map<std::string, invoker_function_type> dictionary_type; dictionary_type m_invokers; public: template<typename Function, typename Base> void register_function(std::string const & name, Function f, Base& base) { m_invokers[name] = ...; //TODO } };
part2 - invoker
invoker是整个实现的核心。其中最重要的是对用户调用函数参数的自适应。
C++代码
- // predefinition
- template<typename Function
- ,typename From = typename mpl::advance_c<typename mpl::begin< ft::parameter_types<Function> >::type, 1>::type
- ,typename To = typename mpl::end< ft::parameter_types<Function> >::type
- >
- struct Invoker;
- // invoker,提取参数,放入sequence,继续调用
- template<typename Function
- ,typename From
- ,typename To
- >
- struct Invoker
- {
- static void apply(Function func) {
- typedef typename mpl::deref<From>::type arg_type; // 当前参数类型
- typedef typename mpl::next<From>::type next_iter_type; // 下一个参数
- typedef Invoker<Function, next_iter_type, To> NextInvoker;
- NextInvoker::apply(func);
- }
- };
- // 特化的invoker,结尾
- template<typename Function
- ,typename To
- >
- struct Invoker<Function,To,To>
- {
- static void apply(Function func) {
- std::cout << "finish";
- }
- };
- template<typename Function>
- void trigger(Function func) {
- Invoker<Function>::apply( func );
- }
// predefinition template<typename Function ,typename From = typename mpl::advance_c<typename mpl::begin< ft::parameter_types<Function> >::type, 1>::type ,typename To = typename mpl::end< ft::parameter_types<Function> >::type > struct Invoker; // invoker,提取参数,放入sequence,继续调用 template<typename Function ,typename From ,typename To > struct Invoker { static void apply(Function func) { typedef typename mpl::deref<From>::type arg_type; // 当前参数类型 typedef typename mpl::next<From>::type next_iter_type; // 下一个参数 typedef Invoker<Function, next_iter_type, To> NextInvoker; NextInvoker::apply(func); } }; // 特化的invoker,结尾 template<typename Function ,typename To > struct Invoker<Function,To,To> { static void apply(Function func) { std::cout << "finish"; } }; template<typename Function> void trigger(Function func) { Invoker<Function>::apply( func ); }
不准确,但是直观的的描述可以理解为:
如果 函数为 func( int, char,void*),则实际生成的模板类分别是
C++代码
- Invoker< Function, int , void >;
- Invoker< Function, char, void >;
- Invoker< Function, void*, void >;
- Invoker< Function, void, void >; //* 这个会匹配到特化的Invoker,从而结束递归
Invoker< Function, int , void >; Invoker< Function, char, void >; Invoker< Function, void*, void >; Invoker< Function, void, void >; //* 这个会匹配到特化的Invoker,从而结束递归
加入收集参数的模板参数
C++代码
- // invoker,提取参数,放入sequence,继续调用
- template<typename Function
- ,typename From
- ,typename To
- >
- struct Invoker
- {
- template< typename Args >
- static void apply(Function func, Args args) {
- typedef typename mpl::deref<From>::type arg_type; // 当前参数类型
- typedef typename mpl::next<From>::type next_iter_type; // 下一个参数
- typedef Invoker<Function, next_iter_type, To> NextInvoker;
- NextInvoker::apply(func, fusion::push_back(args,std::string("hello")));
- }
- };
- // 特化的invoker,结尾
- template<typename Function
- ,typename To
- >
- struct Invoker<Function,To,To>
- {
- template< typename Args >
- static void apply(Function func,Args args) {
- std::cout << args;
- fusion::invoke(func, fusion::push_front(args, input)); // 完成对用户函数的调用
- }
- };
- template<typename Function>
- void trigger(Function func) {
- Invoker<Function>::apply( func , fusion::nil() );
- }
// invoker,提取参数,放入sequence,继续调用 template<typename Function ,typename From ,typename To > struct Invoker { template< typename Args > static void apply(Function func, Args args) { typedef typename mpl::deref<From>::type arg_type; // 当前参数类型 typedef typename mpl::next<From>::type next_iter_type; // 下一个参数 typedef Invoker<Function, next_iter_type, To> NextInvoker; NextInvoker::apply(func, fusion::push_back(args,std::string("hello"))); } }; // 特化的invoker,结尾 template<typename Function ,typename To > struct Invoker<Function,To,To> { template< typename Args > static void apply(Function func,Args args) { std::cout << args; fusion::invoke(func, fusion::push_front(args, input)); // 完成对用户函数的调用 } }; template<typename Function> void trigger(Function func) { Invoker<Function>::apply( func , fusion::nil() ); }
进一步实现对参数的提取,就可以实现一个完整的RPC的机制。
评论暂时关闭