boost asio 学习(六) 定时器

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-
started-with-boostasio?pg=7

6 定时器

boost::asio 提供了一个 deadline_timer class来提供同步与异步的接口。
BOOST文档提供了一组优秀示例。
第一个例子,将创建一个间隔5秒的定时器。

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex global_stream_lock;

void WorkerThread(boost::shared_ptr< boost::asio::io_service > 

io_service)
{
	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Start" << std::endl;
	global_stream_lock.unlock();

	while (true)
	{
		try
		{
			boost::system::error_code ec;
			io_service->run(ec);
			if (ec)
			{
				global_stream_lock.lock();
				std::cout << "[" << 

boost::this_thread::get_id()
					<< "] Error: " << ec << 

std::endl;
				global_stream_lock.unlock();
			}
			break;
		}
		catch (std::exception & ex)
		{
			global_stream_lock.lock();
			std::cout << "[" << 

boost::this_thread::get_id()
				<< "] Exception: " << ex.what() << 

std::endl;
			global_stream_lock.unlock();
		}
	}

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Finish" << std::endl;
	global_stream_lock.unlock();
}

void TimerHandler(const boost::system::error_code & error)
{
	if (error)
	{
		global_stream_lock.lock();
		std::cout << "[" << boost::this_thread::get_id()
			<< "] Error: " << error << std::endl;
		global_stream_lock.unlock();
	}
	else
	{
		global_stream_lock.lock();
		std::cout << "[" << boost::this_thread::get_id()
			<< "] TimerHandler " << std::endl;
		global_stream_lock.unlock();
	}
}

int main(int argc, char * argv[])
{
	boost::shared_ptr< boost::asio::io_service > io_service(
		new boost::asio::io_service
		);
	boost::shared_ptr< boost::asio::io_service::work > work(
		new boost::asio::io_service::work(*io_service)
		);

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Press [return] to exit." << std::endl;
	global_stream_lock.unlock();

	boost::thread_group worker_threads;
	for (int x = 0; x < 2; ++x)
	{
		worker_threads.create_thread(boost::bind

(&WorkerThread, io_service));
	}

	boost::asio::deadline_timer timer(*io_service);
	timer.expires_from_now(boost::posix_time::seconds(5));
	timer.async_wait(TimerHandler);

	std::cin.get();

	io_service->stop();

	worker_threads.join_all();

	return 0;
}

  

如果我们想创建一个可冲用的定时器.我们将定时器对象设置为全局,但是可能
导致共享对象不是线程安全的。boost::bind能解决这个问题。使用定时器对象

的shared_ptr指针,我们能使用bind并且传递定时器到指定的handler,保持定

时器可重用。

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex global_stream_lock;

void WorkerThread(boost::shared_ptr< boost::asio::io_service > 

io_service)
{
	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Start" << std::endl;
	global_stream_lock.unlock();

	while (true)
	{
		try
		{
			boost::system::error_code ec;
			io_service->run(ec);
			if (ec)
			{
				global_stream_lock.lock();
				std::cout << "[" << 

boost::this_thread::get_id()
					<< "] Error: " << ec << 

std::endl;
				global_stream_lock.unlock();
			}
			break;
		}
		catch (std::exception & ex)
		{
			global_stream_lock.lock();
			std::cout << "[" << 

boost::this_thread::get_id()
				<< "] Exception: " << ex.what() << 

std::endl;
			global_stream_lock.unlock();
		}
	}

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Finish" << std::endl;
	global_stream_lock.unlock();
}

void TimerHandler(
	const boost::system::error_code & error,
	boost::shared_ptr< boost::asio::deadline_timer > timer
	)
{
	if (error)
	{
		global_stream_lock.lock();
		std::cout << "[" << boost::this_thread::get_id()
			<< "] Error: " << error << std::endl;
		global_stream_lock.unlock();
	}
	else
	{
		global_stream_lock.lock();
		std::cout << "[" << boost::this_thread::get_id()
			<< "] TimerHandler " << std::endl;
		global_stream_lock.unlock();

		timer->expires_from_now(boost::posix_time::seconds

(5));
		timer->async_wait(boost::bind(&TimerHandler, _1, 

timer));
	}
}

int main(int argc, char * argv[])
{
	boost::shared_ptr< boost::asio::io_service > io_service(
		new boost::asio::io_service
		);
	boost::shared_ptr< boost::asio::io_service::work > work(
		new boost::asio::io_service::work(*io_service)
		);

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Press [return] to exit." << std::endl;
	global_stream_lock.unlock();

	boost::thread_group worker_threads;
	for (int x = 0; x < 2; ++x)
	{
		worker_threads.create_thread(boost::bind

(&WorkerThread, io_service));
	}

	boost::shared_ptr< boost::asio::deadline_timer > timer(
		new boost::asio::deadline_timer(*io_service)
		);
	timer->expires_from_now(boost::posix_time::seconds(5));
	timer->async_wait(boost::bind(&TimerHandler, _1, timer));

	std::cin.get();

	io_service->stop();

	worker_threads.join_all();

	return 0;
}

  

使用bind可以做许多有趣的事情,_1参数是一个占位符。因为TimerHandler 函
数需要一个参数用于回调,我们需要引用这个bind调用。_1意味着第一个参数,

我们稍后提供。

运行上面例子,我们将获得一个每五秒激活一次的定时器。
如果想保证定时器不和work处理器同时运行,我们可以使用strand。
代码如下

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex global_stream_lock;

void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service)
{
	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Start" << std::endl;
	global_stream_lock.unlock();

	while (true)
	{
		try
		{
			boost::system::error_code ec;
			io_service->run(ec);
			if (ec)
			{
				global_stream_lock.lock();
				std::cout << "[" << boost::this_thread::get_id()
					<< "] Error: " << ec << std::endl;
				global_stream_lock.unlock();
			}
			break;
		}
		catch (std::exception & ex)
		{
			global_stream_lock.lock();
			std::cout << "[" << boost::this_thread::get_id()
				<< "] Exception: " << ex.what() << std::endl;
			global_stream_lock.unlock();
		}
	}

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Thread Finish" << std::endl;
	global_stream_lock.unlock();
}

void TimerHandler(
	const boost::system::error_code & error,
	boost::shared_ptr< boost::asio::deadline_timer > timer,
	boost::shared_ptr< boost::asio::io_service::strand > strand
	)
{
	if (error)
	{
		global_stream_lock.lock();
		std::cout << "[" << boost::this_thread::get_id()
			<< "] Error: " << error << std::endl;
		global_stream_lock.unlock();
	}
	else
	{
		std::cout << "[" << boost::this_thread::get_id()
			<< "] TimerHandler " << std::endl;

		timer->expires_from_now(boost::posix_time::seconds(1));
		timer->async_wait(
			strand->wrap(boost::bind(&TimerHandler, _1, timer, strand))
			);
	}
}

void PrintNum(int x)
{
	std::cout << "[" << boost::this_thread::get_id()
		<< "] x: " << x << std::endl;
	boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}

int main(int argc, char * argv[])
{
	boost::shared_ptr< boost::asio::io_service > io_service(
		new boost::asio::io_service
		);
	boost::shared_ptr< boost::asio::io_service::work > work(
		new boost::asio::io_service::work(*io_service)
		);
	boost::shared_ptr< boost::asio::io_service::strand > strand(
		new boost::asio::io_service::strand(*io_service)
		);

	global_stream_lock.lock();
	std::cout << "[" << boost::this_thread::get_id()
		<< "] Press [return] to exit." << std::endl;
	global_stream_lock.unlock();

	boost::thread_group worker_threads;
	for (int x = 0; x < 2; ++x)
	{
		worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
	}

	boost::this_thread::sleep(boost::posix_time::seconds(1));

	strand->post(boost::bind(&PrintNum, 1));
	strand->post(boost::bind(&PrintNum, 2));
	strand->post(boost::bind(&PrintNum, 3));
	strand->post(boost::bind(&PrintNum, 4));
	strand->post(boost::bind(&PrintNum, 5));

	boost::shared_ptr< boost::asio::deadline_timer > timer(
		new boost::asio::deadline_timer(*io_service)
		);
	timer->expires_from_now(boost::posix_time::seconds(1));
	timer->async_wait(
		strand->wrap(boost::bind(&TimerHandler, _1, timer, strand))
		);

	std::cin.get();

	io_service->stop();

	worker_threads.join_all();

	return 0;
}

  

我们需要使用strand封装定时器处理器,strand能确保工作对象先运行而后定时器线程后运行。

本章节我们学习如何使用bind strand shard_ptr来获取灵活性和实现功能。在后面的网络系统中我们将使用这些组件。

时间: 2024-12-19 07:09:48

boost asio 学习(六) 定时器的相关文章

boost::asio学习(定时器)

#include <boost/asio.hpp> #include <iostream> void handle1(const boost::system::error_code& ec) { std::cout << "5.s" << std::endl; } void handle2(const boost::system::error_code& ec) { std::cout << "10.

boost asio 学习(九) boost::asio 网络封装

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=10 9. A boost::asio network wrapper (TCP) 现在我们了解asio和TCP网络方面的知识,我们可以尝试下封装网络底层.通过使用这个封装,我们可以重用代码并且将精力集中于业务逻 辑方面而不在网络通讯方面花费太多精力. 重要提示:本代码仅仅用于教学目的.不要在商业系统中使用该代码,

boost asio 学习(七) 网络基础 连接器和接收器(TCP示例)

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=8 7. Networking basics: connectors and acceptors (TCP)我们来学习boost的TCP网络编程.之前的篇章已经介绍了网络系统框架.我们只需要学习网络API函数即可 我们首先学习如何同步的连接主机.我们的代码作为客户端运行,使用tcp::socket对象.tcp::s

boost asio学习笔记 [1] - 同步通讯

本文以一段示例代码,说明使用boost asio进行同步通讯的使用方法. #include <iostream> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::tcp;  int main() {     boost::asio::io_service   ioservice;             // I/O事件模型封装,如win下的iocp,unix下的poll, linux下的e

BOOST ASIO 学习专贴

1.同步使用Timer 本便使用了boost::asio::deadline_timer,这个timer有两种状态:过期和不过期.wait函数调用一个过期的timer直接返回. int _tmain(int argc, _TCHAR* argv[]) { boost::asio::io_service io; boost::asio::deadline_timer t(io,boost::posix_time::seconds(5)); t.wait(); std::cout<<"w

boost asio 学习(五) 错误处理

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=6 5. Error handling 接下来我们需要注意的话题是错误处理.换句话说就是函数抛出异常时发生了什么 Boost::asio 给予用户两种选择来处理.错误通过handler传播,指出线程呼叫run或者poll系列函数的位置.用户可以能处理通过异常抛出的状态或者是接收返回的错误变量.更多关于BOOST的信息

boost asio 学习(三)

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=4 本章节为io_service添加任务,并且区分dispatch与post的区别.如果说io_service是asio库的大脑,那么post与dispatch就是asio库的手和脚. 先看看示例1 #include <boost/asio.hpp> #include <boost/shared_ptr.hp

Boost.Asio学习笔记一、linux下boost库的安装

学习开源库的第一步就是,编译安装,然后我们才能写一写demo去测试. 所以本章我们学一下在linux编译安装Boost库,为了方便起见,直接安装完整库. 我使用的版本是boost_1_55_0,版本差别不大. [[email protected] ~]$ tar -zxvf boost_1_55_0.tar.gz [[email protected] boost_1_55_0]$ ./bootstrap.sh --prefix=/home/mjf/lib [[email protected] b

boost asio 翻译(一)

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/ 编译环境 boost1.59  vs2015 A guide to getting started with boost::asioboost asio 学习指南 boost::asio是一个使用现代C++方法为开发者提供异步模型的跨平台的c++网络和 底层IO库.目前已经拥有大量用户并成为boost库的一部分 在开始之