如何在120行内实现一个有协程并支持tbus的服务器框架

来源:互联网 发布:碧海潮生曲 知乎 编辑:程序博客网 时间:2024/06/05 02:53

目前协程很火,于是决定搞一个框架试试,下面的代码很短,不过麻雀虽小,五脏俱全。目前支持tbus,配上boost::asio,可以很容易的支持tcp,udp,异步文件读写等操作。

附linux下编译指令:
g++ server.cpp -I$(BOOST_ROOT) -o server \
$(BOOST_ROOT)/stage/lib/libboost_coroutine.a\
$(BOOST_ROOT)/stage/lib/libboost_context.a\
$(BOOST_ROOT)/stage/lib/libboost_system.a\
$(BOOST_ROOT)/stage/lib/libboost_thread.a -lpthread -lrt


#include <boost/asio.hpp>#include <boost/coroutine/all.hpp>#include <boost/bind.hpp>#include <boost/thread.hpp>#include <boost/chrono.hpp>#include <boost/shared_ptr.hpp>namespace ba = boost::asio;class fake_tbus{public:fake_tbus():m_trans_id(0),m_msg("initial request"){}void tbus_send(int trans_id, std::string buf){m_trans_id = trans_id;m_msg = buf;std::cout << "tbus_send: " << trans_id << ": " << m_msg << std::endl;}std::string tbus_recv(int& trans_id){trans_id = m_trans_id;std::cout << "tbus_recv: " << trans_id << ": " << m_msg << std::endl;return m_msg;}private:int m_trans_id;std::string m_msg;};class server{public:typedef boost::coroutines::asymmetric_coroutine<std::string>::push_type push_type;typedef boost::coroutines::asymmetric_coroutine<std::string>::pull_type pull_type;typedef boost::shared_ptr<push_type> push_type_ptr;typedefstd::map<int, push_type_ptr> coroutine_map_t;;server():m_stop(false){}void run(){int global_trans_id = 0;while (!m_stop){int tbus_trans_id = 0;std::string buf = m_tbus.tbus_recv(tbus_trans_id);push_type_ptr p_push;// this is an new request, so we create a new coroutine.if (tbus_trans_id == 0){global_trans_id++;p_push.reset(new push_type(boost::bind(&server::tbus_handler, this, global_trans_id, _1)));m_coroutines.insert(std::make_pair(global_trans_id, p_push));                tbus_trans_id = global_trans_id;}// this should be in a transaction, find the coroutine dealing with it.else{coroutine_map_t::iterator it = m_coroutines.find(tbus_trans_id);if (it != m_coroutines.end()){p_push = it->second;}}if (p_push){// to the next step.bool has_next = (*p_push)(buf);if (!has_next){// if coroutine has returnd, finish it.m_coroutines.erase(tbus_trans_id);}}boost::this_thread::sleep_for(boost::chrono::seconds(1));}}// our handler function.void tbus_handler(int trans_id, pull_type& pull){std::string req = get_request(pull);std::cout << "tbus_handler req:  " << req << std::endl;std::string res = yield_async_send(trans_id, pull, "hello");std::cout << "tbus_handler res1:  " << res << std::endl;res = yield_async_send(trans_id, pull, "world");std::cout << "tbus_handler res2: " << res << std::endl;}std::string yield_async_send(int trans_id, pull_type& pull, std::string buf){m_tbus.tbus_send(trans_id, buf);pull();return pull.get();}    std::string get_request(pull_type& pull){return pull.get();}    coroutine_map_t m_coroutines;bool m_stop;fake_tbus m_tbus;};int main(int argc, char* argv[]){server s;s.run();return 0;}/*输出:tbus_recv: 0: initial requesttbus_handler req:  initial requesttbus_send: 1: hellotbus_recv: 1: hellotbus_handler res1:  hellotbus_send: 1: worldtbus_recv: 1: worldtbus_handler res2: worldtbus_recv: 1: worldtbus_recv: 1: worldtbus_recv: 1: worldtbus_recv: 1: worldtbus_recv: 1: world*/


0 0