标准库条件变量等待时间受系统时间影响

std::condition_variable bug

​ wait_until受系统时间修改导致等待不准确 (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) )

​ 代码中使用了std::condition_variable 来实现信号量,但是当修改了系统时间后会导致信号量提前(往后改系统时间)延后触发(往前改系统时间),究其原因是信号量的wait_for 或 wait_until接口以系统时钟作为标准导致。**

实例测试代码

采用usleep std::sleep_for boost::condition_variable std::condition_variable 作比较 ,程序启动后往后前调整几秒钟时间。

#include"toolkit/std_threadpool.hpp"				//线程池	
#include <iostream>
#include<functional>
#include <thread>
#include "toolkit/elapsed_timer.hpp"				//计时器
#include "toolkit/semaphore.hpp"					//信号量
#include <boost/interprocess/sync/interprocess_semaphore.hpp>//boost信号量
#include <boost/date_time.hpp>
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
using std::cout;
using std::endl;


#include<unistd.h>

void do_usleep(int ms)
{
	AS120::elapsed_timer time;
	cout << __FUNCTION__ << " "<< ms << " MS start!"<<endl;
	usleep(ms*1000);

	cout << __FUNCTION__ << " "<< ms << " MS over!   "<< time.elasped()<<endl;
}
void do_std_sleep_for(int ms)
{
	AS120::elapsed_timer time;
	cout << __FUNCTION__ << " "<< ms << " MS start!"<<endl;
	std::this_thread::sleep_for(std::chrono::milliseconds(ms));
	cout << __FUNCTION__ << " "<< ms << " MS over!"<< time.elasped()<<endl;
}

void do_boost_cv_wait(int ms)
{
	cout << __FUNCTION__ << " "<< ms << " MS start!"<<endl;

	AS120::elapsed_timer time;
	boost::mutex mtx;
	boost::condition_variable cv;
	boost::unique_lock<boost::mutex> lk(mtx);
	auto finished = cv.wait_until(lk, boost::chrono::steady_clock::now() +
		boost::chrono::milliseconds(ms), [&] {
			return	false;
		});
	
	cout << __FUNCTION__ << " "<< ms << " MS over!"<< time.elasped()<<endl;
}


void do_std_cv_wait(int ms)
{
	cout << __FUNCTION__ << " "<< ms << " MS start!"<<endl;

	AS120::elapsed_timer time;
	std::mutex mtx;
	std::condition_variable cv;
	std::unique_lock<std::mutex> lk(mtx);
	auto finished = cv.wait_until(lk, std::chrono::steady_clock::now() +
		std::chrono::milliseconds(ms), [&] {
			return	false;
		});
	
	cout << __FUNCTION__ << " "<< ms << " MS over!"<< time.elasped()<<endl;
}


void do_semaphore_wait(int ms)
{
	cout << __FUNCTION__ << " "<< ms << " MS start!"<<endl;
	AS120::elapsed_timer time;
	AS120::semaphore sem;
	sem.timed_wait_ms(ms);
	cout << __FUNCTION__ << " "<< ms << " MS over!"<< time.elasped()<<endl;

}

int main(int argc,char** argv)
{
	AS120::std_threadpool pl(10);
	int TIME_MS = 20000;
	if (argc > 1)
	{
		TIME_MS = std::stoi(argv[1]);
	}
	cout <<"TIME_MS is " << TIME_MS << endl;
	pl.schedule([](int ms){
		do_usleep(ms);
	},TIME_MS);

	pl.schedule([](int ms){
		do_std_sleep_for(ms);
	},TIME_MS);
	pl.schedule([](int ms){
		do_boost_cv_wait(ms);
	},TIME_MS);
	pl.schedule([](int ms){
		do_std_cv_wait(ms);
	},TIME_MS);


	
	getchar();
}

输出

TIME_MS is 20000
do_usleep 20000 MS start!
do_std_sleep_for 20000 MS start!
do_boost_cv_wait 20000 MS start!
do_std_cv_wait 20000 MS start!
do_boost_cv_wait 20000 MS over!20000
do_std_sleep_for 20000 MS over!20000
do_usleep 20000 MS over!   20000
do_std_cv_wait 20000 MS over!25660

说明标准库的条件变量等待的时间不准一点都不steady

项目中替换为boost::condition_variable

替换为boost库后 信号量实现的头文件更换为了

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/chrono.hpp>

由于信号量为hpp头文件库 且项目中大量使用的是标准库,估计头文件污染导致程序crash(heap-buffer-overflow ,双析构)奇怪的情况。

必须重写信号量 将定义h和实现cpp分离开 防止boost的头文件污染到标准库中。

目前可行。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值