基于C++11的可中断睡眠功能实现

源文件

InterruptibleSleep.h

#pragma once

#include <atomic>
#include <chrono>
#include <mutex>

namespace UtilityTools {
	using namespace std;

	class InterruptibleSleep
	{
	public:
		bool start(const chrono::milliseconds & durInMS);
		bool interrupt();
		bool isSleeping() const;
		bool isInterrupted() const;

	private:
		mutex m_alertGrd;
		condition_variable m_alertSig;
		atomic_bool m_bAlert{ false };
		atomic_bool m_bSlping{ false };
	};
}

InterruptibleSleep.cpp

#include "InterruptibleSleep.h"

using namespace std;

bool UtilityTools::InterruptibleSleep::start(const chrono::milliseconds & durInMS)
{
	if (m_bSlping) return false;
	unique_lock<mutex> lock(m_alertGrd);
	m_bAlert = false;
	m_bSlping = true;
	m_alertSig.wait_for(lock, durInMS, [this]() { return m_bAlert.load(); });
	m_bSlping = false;
	return true;
}

bool UtilityTools::InterruptibleSleep::interrupt()
{
	if (!m_bSlping) return false;
	{
		lock_guard<mutex> lock(m_alertGrd);
		m_bAlert = true;
	}
	m_alertSig.notify_all();
	return true;
}

bool UtilityTools::InterruptibleSleep::isSleeping() const { 
	return m_bSlping; 
}

bool UtilityTools::InterruptibleSleep::isInterrupted() const {
	return m_bAlert; 
}

测试代码

#include "InterruptibleSleep.h"

#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <sstream>

using namespace std;
using namespace chrono_literals;
using namespace UtilityTools;

std::string currentTime()
{
	using namespace std::chrono;

	// get current time
	auto now = system_clock::now();

	// get number of milliseconds for the current second
	// (remainder after division into seconds)
	auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;

	// convert to time_t in order to convert to tm (broken time)
	auto timer = system_clock::to_time_t(now);

	// convert to broken time
	#pragma warning(suppress : 4996)
	tm bt = *localtime(&timer);

	ostringstream oss;

	oss << put_time(&bt, "%H:%M:%S"); // HH:MM:SS
	oss << '.' << setfill('0') << setw(3) << ms.count();

	return oss.str();
}

void printLog(const string & sLog)
{
	static mutex mtx;
	lock_guard<mutex> lg(mtx);
	cout << "[" << currentTime() << "] " << sLog << endl;
}

atomic<bool> exitThread = false;

InterruptibleSleep iSlp;

void timerThread()
{
	auto timeout = 100ms;
	while (!exitThread) {
		if (!iSlp.start(timeout)) {
			cout << "Fail to sleep" << endl;
			return;
		} else { /* Do nothing */ }
		if (exitThread) {
			printLog("Timer thread exiting.");
			return;
		} else if (iSlp.isInterrupted()) {
			printLog("Timer was interrupted due to alert.");
		} else {
			printLog("Timer achieved time-out.");
		}
	}
}

int main()
{
	thread threadWait(&timerThread);

	printLog("main(): Waiting 300ms...");
	this_thread::sleep_for(300ms);
	printLog("main(): Sim. interrupt.");
	iSlp.interrupt();

	printLog("main(): Waiting 50 ms...");
	this_thread::sleep_for(50ms);
	printLog("main(): Sim. interrupt.");
	iSlp.interrupt();

	printLog("main(): Waiting 50 ms...");
	this_thread::sleep_for(50ms);
	exitThread = true;
	iSlp.interrupt();
	threadWait.join();
	printLog("Done.");
}

测试输出

[19:53:16.875] main(): Waiting 300ms...
[19:53:16.994] Timer achieved time-out.
[19:53:17.120] Timer achieved time-out.
[19:53:17.198] main(): Sim. interrupt.
[19:53:17.199] main(): Waiting 50 ms...
[19:53:17.200] Timer was interrupted due to alert.
[19:53:17.266] main(): Sim. interrupt.
[19:53:17.266] Timer was interrupted due to alert.
[19:53:17.267] main(): Waiting 50 ms...
[19:53:17.331] Timer thread exiting.
[19:53:17.332] Done.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值