【Boost】boost库asio详解3——io_service作为work pool

<span style="font-family: Arial, Helvetica, sans-serif;">#include <stdio.h> </span>
#include <cstdlib> 
#include <iostream> 
#include <boost/thread.hpp> 
#include <boost/aligned_storage.hpp> 
#include <boost/array.hpp> 
#include <boost/bind.hpp> 
#include <boost/enable_shared_from_this.hpp> 
#include <boost/noncopyable.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/asio.hpp> 

using boost::asio::ip::tcp; 

class handler_allocator 
	: private boost::noncopyable 
{ 
public: 
	handler_allocator() 
		: in_use_(false) 
	{ 
	} 

	void* allocate(std::size_t size) 
	{ 
		if (!in_use_ && size < storage_.size) 
		{ 
			in_use_ = true; 
			return storage_.address(); 
		} 
		else 
		{ 
			return ::operator new(size); 
		} 
	} 

	void deallocate(void* pointer) 
	{ 
		if (pointer == storage_.address()) 
		{ 
			in_use_ = false; 
		} 
		else 
		{ 
			::operator delete(pointer); 
		} 
	} 

private: 
	// Storage space used for handler-based custom memory allocation. 
	boost::aligned_storage<1024> storage_; 

	// Whether the handler-based custom allocation storage has been used. 
	bool in_use_; 
}; 

template <typename Handler> 
class custom_alloc_handler 
{ 
public: 
	custom_alloc_handler(handler_allocator& a, Handler h) 
		: allocator_(a), 
		handler_(h) 
	{ 
	} 

	template <typename Arg1> 
	void operator()(Arg1 arg1) 
	{ 
		handler_(arg1); 
	} 

	template <typename Arg1, typename Arg2> 
	void operator()(Arg1 arg1, Arg2 arg2) 
	{ 
		handler_(arg1, arg2); 
	} 

	friend void* asio_handler_allocate(std::size_t size, 
		custom_alloc_handler<Handler>* this_handler) 
	{ 
		return this_handler->allocator_.allocate(size); 
	} 

	friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/, 
		custom_alloc_handler<Handler>* this_handler) 
	{ 
		this_handler->allocator_.deallocate(pointer); 
	} 

private: 
	handler_allocator& allocator_; 
	Handler handler_; 
}; 

// Helper function to wrap a handler object to add custom allocation. 
template <typename Handler> 
inline custom_alloc_handler<Handler> make_custom_alloc_handler( 
	handler_allocator& a, Handler h) 
{ 
	return custom_alloc_handler<Handler>(a, h); 
} 

/// A pool of io_service objects. 
class io_service_pool 
	: private boost::noncopyable 
{ 
public: 
	/// Construct the io_service pool. 
	explicit io_service_pool(std::size_t pool_size) : next_io_service_(0) 
	{ 
		if (pool_size == 0) 
			throw std::runtime_error("io_service_pool size is 0"); 

		// Give all the io_services work to do so that their run() functions will not 
		// exit until they are explicitly stopped. 
		for (std::size_t i = 0; i < pool_size; ++i) 
		{ 
			io_service_ptr io_service(new boost::asio::io_service); 
			work_ptr work(new boost::asio::io_service::work(*io_service)); 
			io_services_.push_back(io_service); 
			work_.push_back(work); 
		} 
	} 

	// Run all io_service objects in the pool. 
	void run() 
	{ 
		// Create a pool of threads to run all of the io_services. 
		std::vector<boost::shared_ptr<boost::thread> > threads; 
		for (std::size_t i = 0; i < io_services_.size(); ++i) 
		{ 
			boost::shared_ptr<boost::thread> thread(new boost::thread( 
				boost::bind(&boost::asio::io_service::run, io_services_[i]))); 
			threads.push_back(thread); 
		} 

		// Wait for all threads in the pool to exit. 
		for (std::size_t i = 0; i < threads.size(); ++i) 
			threads[i]->join(); 
	} 

	// Stop all io_service objects in the pool. 
	void stop() 
	{ 
		// Explicitly stop all io_services. 
		for (std::size_t i = 0; i < io_services_.size(); ++i) 
			io_services_[i]->stop(); 
	} 

	// Get an io_service to use. 
	boost::asio::io_service& get_io_service() 
	{ 
		// Use a round-robin scheme to choose the next io_service to use. 
		boost::asio::io_service& io_service = *io_services_[next_io_service_]; 
		++next_io_service_; 
		if (next_io_service_ == io_services_.size()) 
			next_io_service_ = 0; 
		return io_service; 
	} 

private: 
	typedef boost::shared_ptr<boost::asio::io_service> io_service_ptr; 
	typedef boost::shared_ptr<boost::asio::io_service::work> work_ptr; 

	/// The pool of io_services. 
	std::vector<io_service_ptr> io_services_; 

	/// The work that keeps the io_services running. 
	std::vector<work_ptr> work_; 

	/// The next io_service to use for a connection. 
	std::size_t next_io_service_; 
}; 

class session 
	: public boost::enable_shared_from_this<session> 
{ 
public: 
	session(boost::asio::io_service& work_service
		, boost::asio::io_service& io_service) 
		: socket_(io_service) 
		, io_work_service(work_service) 
	{ 
	} 

	tcp::socket& socket() 
	{ 
		return socket_; 
	} 

	void start() 
	{ 
		socket_.async_read_some(boost::asio::buffer(data_), 
			make_custom_alloc_handler(allocator_, 
			boost::bind(&session::handle_read, 
			shared_from_this(), 
			boost::asio::placeholders::error, 
			boost::asio::placeholders::bytes_transferred))); 
	} 

	void handle_read(const boost::system::error_code& error, 
		size_t bytes_transferred) 
	{ 
		if (!error) 
		{ 
			boost::shared_ptr<std::vector<char> > buf(new std::vector<char>); 

			buf->resize(bytes_transferred); 
			std::copy(data_.begin(), data_.begin() + bytes_transferred, buf->begin()); 
			io_work_service.post(boost::bind(&session::on_receive
				, shared_from_this(), buf, bytes_transferred)); 

			socket_.async_read_some(boost::asio::buffer(data_), 
				make_custom_alloc_handler(allocator_, 
				boost::bind(&session::handle_read, 
				shared_from_this(), 
				boost::asio::placeholders::error, 
				boost::asio::placeholders::bytes_transferred))); 
		} 
	} 

	void handle_write(const boost::system::error_code& error) 
	{ 
		if (!error) 
		{ 
		} 
	} 

	void on_receive(boost::shared_ptr<std::vector<char> > buffers
		, size_t bytes_transferred) 
	{ 
		char* data_stream = &(*buffers->begin()); 
		// in here finish the work. 
		std::cout << "receive :" << bytes_transferred << " bytes." << 
			"message :" << data_stream << std::endl; 
	} 

private: 
	// The io_service used to finish the work. 
	boost::asio::io_service& io_work_service; 

	// The socket used to communicate with the client. 
	tcp::socket socket_; 

	// Buffer used to store data received from the client. 
	boost::array<char, 1024> data_; 

	// The allocator to use for handler-based custom memory allocation. 
	handler_allocator allocator_; 
}; 

typedef boost::shared_ptr<session> session_ptr; 

class server 
{ 
public: 
	server(short port, std::size_t io_service_pool_size) 
		: io_service_pool_(io_service_pool_size) 
		, io_service_work_pool_(io_service_pool_size) 
		, acceptor_(io_service_pool_.get_io_service(), tcp::endpoint(tcp::v4(), port)) 
	{ 
		session_ptr new_session(new session(io_service_work_pool_.get_io_service()
			, io_service_pool_.get_io_service())); 
		acceptor_.async_accept(new_session->socket(), 
			boost::bind(&server::handle_accept, this, new_session, 
			boost::asio::placeholders::error)); 
	} 

	void handle_accept(session_ptr new_session, 
		const boost::system::error_code& error) 
	{ 
		if (!error) 
		{ 
			new_session->start(); 
			new_session.reset(new session(io_service_work_pool_.get_io_service()
				, io_service_pool_.get_io_service())); 
			acceptor_.async_accept(new_session->socket(), 
				boost::bind(&server::handle_accept, this, new_session, 
				boost::asio::placeholders::error)); 
		} 
	} 

	void run() 
	{ 
		io_thread_.reset(new boost::thread(boost::bind(&io_service_pool::run
			, &io_service_pool_))); 
		work_thread_.reset(new boost::thread(boost::bind(&io_service_pool::run
			, &io_service_work_pool_))); 
	} 

	void stop() 
	{ 
		io_service_pool_.stop(); 
		io_service_work_pool_.stop(); 

		io_thread_->join(); 
		work_thread_->join(); 
	} 

private: 
	boost::shared_ptr<boost::thread> io_thread_; 
	boost::shared_ptr<boost::thread> work_thread_; 
	io_service_pool io_service_pool_; 
	io_service_pool io_service_work_pool_; 
	tcp::acceptor acceptor_; 
}; 

int main(int argc, char* argv[]) 
{ 
	try 
	{ 
		if (argc != 2) 
		{ 
			std::cerr << "Usage: server <port>/n"; 
			return 1; 
		} 

		using namespace std; // For atoi. 
		server s(atoi(argv[1]), 10); 

		s.run(); 

		getchar(); 

		s.stop(); 
	} 
	catch (std::exception& e) 
	{ 
		std::cerr << "Exception: " << e.what() << "/n"; 
	} 

	return 0; 
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`boost::asio::io_service`是Boost中的一个核心类,用于提供异步I/O操作的事件循环机制。它是实现异步网络编程的基础,可用于处理各种网络通信任务。 `boost::asio::io_service`的主要作用是管理和调度异步操作。它负责处理事件循环,监视和分发I/O事件,以及执行注册的回调函数。通过使用`io_service`对象,可以实现非阻塞式的异步I/O编程,提高程序的并发性和响应性。 以下是`boost::asio::io_service`类的常见用法示例: ```cpp #include <boost/asio.hpp> void handleRead(const boost::system::error_code& error, std::size_t bytes_transferred) { if (!error) { // 处理读取数据的回调逻辑 } else { // 处理错误情况 } } int main() { boost::asio::io_service io_service; // 创建一个socket对象 boost::asio::ip::tcp::socket socket(io_service); // 连接到服务器 socket.connect(endpoint); // 异步读取数据 boost::asio::async_read(socket, boost::asio::buffer(buffer), handleRead); // 开始事件循环 io_service.run(); return 0; } ``` 在上述示例中,首先创建了一个`io_service`对象,然后创建了一个TCP socket对象,并使用`io_service`对象进行异步读取操作。在`async_read`函数中,指定了一个回调函数`handleRead`,用于处理读取数据完成后的回调逻辑。 最后,通过调用`io_service`的`run()`函数启动事件循环,使程序进入等待事件的状态。在事件循环中,`io_service`会不断地监视和分发I/O事件,并执行注册的回调函数。 使用`boost::asio::io_service`,可以方便地实现异步的网络编程,处理各种I/O操作,如读取、写入、连接、接收等。它提供了高度灵活和可扩展的方式来构建异步应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值