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

目前协程很火,于是决定搞一个框架试试,下面的代码很短,不过麻雀虽小,五脏俱全。目前支持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;

	typedef	std::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 request
tbus_handler req:  initial request
tbus_send: 1: hello
tbus_recv: 1: hello
tbus_handler res1:  hello
tbus_send: 1: world
tbus_recv: 1: world
tbus_handler res2: world
tbus_recv: 1: world
tbus_recv: 1: world
tbus_recv: 1: world
tbus_recv: 1: world
tbus_recv: 1: world
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值