1. 程式人生 > >gflags用法與boost非同步I/O服務經典示例

gflags用法與boost非同步I/O服務經典示例

(第一次從專案中接觸這類知識,還是挺好奇,於是自己寫了一段)

gflags是google的一套開源命令列引數解析工具,在工程化的開發當中經常用到,其安裝可以參考網上,下面僅演示gflags的引數定義、引數檢查、引數傳入。

boost是是一個可移植、提供原始碼的C++庫,作為標準庫的後備,是C++標準化程序的開發引擎之一。c++標準一直都在變,現在c++11用得比較多,但以前的工程裡一直還是習慣使用boost,所以要看懂以前的程式碼,boost還是要看一下的,下面演示了boost非同步服務,通過定時器實現定時輸出功能,並實現了類之間的回撥。

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include "gflags/gflags.h"
#include <iostream>


static int second = 0;
boost::shared_mutex myMutex;
//定義等待時間
DEFINE_int32(timer_wait_second,2,"wait time in seconds");

class myClass
{
public:
	myClass() :myAge(20), myName("alpc40") {}
	bool setAgeName(const int age, const std::string name) {
		myAge = age;
		myName = name;
		return true;
	}
	void outAgeName() {
		std::cout << myAge << " " << myName <<std::endl;
	}

private:
	int myAge;
	std::string myName;
};


class cls
{
	//定義回撥形式,與myClass相關
	using callBack = std::function<bool(const int, const std::string)>;
	using printCallBack = std::function<void(void)>;
public:
	cls();
	~cls();
	void print(const boost::system::error_code &ec);
	void RegisteUserCallBack(callBack call_back);
	void RegistePrintCallBack(printCallBack call_back);
private:
	boost::asio::io_service io_service;
	boost::asio::deadline_timer timer;
	boost::thread* thread;
	callBack my_call_back;
	printCallBack my_print_call_back;
};
//回撥函式
void cls::RegistePrintCallBack(printCallBack call_back)
{
	my_print_call_back = call_back;
}
//回撥函式
void cls::RegisteUserCallBack(callBack call_back)
{
	my_call_back = call_back;
}

cls::cls() : timer(io_service, boost::posix_time::seconds(FLAGS_timer_wait_second)) {
	//timer繫結函式,即當timer結束後,才啟動該函式
	timer.async_wait(boost::bind(&cls::print, this, boost::asio::placeholders::error));
	thread = new boost::thread([&] {
		//io_service開始工作,這個時候timer才開始啟動
		boost::asio::io_service::work work(io_service);
		//非同步阻塞,直到work完成才能結束
		io_service.run();
	});
}

cls::~cls() {
	//釋放時先取消定時器
	timer.cancel();
	//取消非同步IO服務
	io_service.stop();
	//取消執行緒
	if (thread != nullptr) {
		//執行緒阻塞,直到thread執行完畢
		thread->join();
		delete thread;
		thread = nullptr;
	}
}

void cls::print(const boost::system::error_code &ec)
{
	printf("%d s\n", ++second);
	//使用鎖,寫myClass類
	boost::unique_lock<boost::shared_mutex> _(myMutex);
	my_call_back(second, "haha");
	my_print_call_back();
	if (second < 8)
	{
		//使timer重新激發,繼續執行
		timer.expires_from_now(boost::posix_time::seconds(FLAGS_timer_wait_second));
		timer.async_wait(boost::bind(&cls::print, this, boost::asio::placeholders::error));
	}
	
}
//引數賦值檢測函式,使1<FLAGS_timer_wait_second< 60
static bool validateTimer(const char *name, int32_t second)
{
	if (second > 60 || second < 1)
		return false;
	return true;
}

int main(int argc,char **argv)
{
	//註冊引數賦值檢測函式
	gflags::RegisterFlagValidator(&FLAGS_timer_wait_second, &validateTimer);
	//引數來自輸入,自行賦值給FLAGS
	gflags::ParseCommandLineFlags(&argc, &argv, true);
	//定義兩個類
	myClass heihei;
	cls haha;
	//註冊函式,也就是說,在haha類當中可以呼叫heihei類,使heihei類進行改變
	haha.RegisteUserCallBack(std::bind(&myClass::setAgeName, &heihei, std::placeholders::_1, std::placeholders::_2));
	haha.RegistePrintCallBack(std::bind(&myClass::outAgeName, &heihei));
	while (1)
	{
		Sleep(1000);
		//獲得主執行緒ID
		std::cout << boost::this_thread::get_id() << ":";
		//獲得鎖,防止輸出時輸入
		boost::unique_lock<boost::shared_mutex> _(myMutex);
		heihei.outAgeName();
	}
	return 0;
}

可以執行下,看看效果與自己的期望是不是一樣,還是挺有意思的