• 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来获取灵活性和实现功能。在后面的网络系统中我们将使用这些组件。

  • 相关阅读:
    linux c使用socket进行http 通信,并接收任意大小的http响应(四)
    linux c使用socket进行http 通信,并接收任意大小的http响应(三)
    Linux c读取系统内存使用信息
    linux c使用socket进行http 通信,并接收任意大小的http响应(二)
    linux c使用socket进行http 通信,并接收任意大小的http响应(一)
    Linux c读取任意大小文件的所有数据
    Linux c 从文件当中读取任意一行的数据
    如何抓取Android系统APP运行测试日志
    Linux下将Weblogic设置为开机启动
    Red hat/CentOS7关闭防火
  • 原文地址:https://www.cnblogs.com/itdef/p/5618228.html
Copyright © 2020-2023  润新知