我正在尝试为wait()方法实现线程,这样它就不会阻塞main()线程。
在主线程中,wait()函数必须每小时运行一次validate函数。因此,当wait()函数运行时,main()线程被阻塞,并且不会继续执行任何代码,直到wait()函数完成或线程被加入。因此,我想独立于main()运行wait()。
main.cpp
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/stat.h>
#include <boost/date_time.hpp>
#include <boost/thread/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <pthread.h>
using namespace std;
constexpr char clock_file[] = "/home/saman/Desktop/clock";
constexpr char sync_file[] = "/home/saman/Desktop/hi/hi/synchronized";
class TimeEvent {
public:
void receive_time_event(timespec& time) {
// Create clock file
ofstream clockFile(clock_file);
if (!clockFile.is_open()) {
cout << "Failed to open file" << endl;
}
clockFile.close();
// Create synchronized file
boost::filesystem::path dir(sync_file);
boost::filesystem::create_directories(dir.parent_path());
ofstream synchronizedFile(sync_file);
if (!synchronizedFile.is_open()) {
cout << "Failed to open file" << endl;
}
synchronizedFile.close();
}
timespec get_latest_clock_entry(){
cout << "hello" << endl;
}
void wait(){
while(1){
cout << "start wait" << endl;
auto Now_Time = boost::posix_time::second_clock::local_time();
auto update_Time = Now_Time + boost::posix_time::minutes(1);
auto counter = update_Time - Now_Time;
boost::this_thread::sleep(counter);
validate();
}
}
void validate(){
// cout << "hi" << endl;
timespec currentTime;
timespec_get(¤tTime, TIME_UTC);
timespec ModifiedTime = get_latest_clock_entry();
if (currentTime.tv_sec > ModifiedTime.tv_sec){
ofstream clockfile(clock_file);
if (!clockfile.is_open()) {
cout << "Failed to open file" << endl;
}
clockfile.close();
}
// update system time to match the clock file's modified time
int result = clock_settime(CLOCK_REALTIME, &ModifiedTime);
if(result == 0){
cout<< "updated system time to current time" << endl;
}
else{
cout<< "failed to update system time" << endl;
}
}
void update_system_time_on_startup() {
cout << "hello" << endl;
};
int main() {
TimeEvent timeEvent;
timespec time;
timespec_get(&time, TIME_UTC);
cout << "hello" << endl;
timeEvent.receive_time_event(time);
auto lastModifiedTime = timeEvent.get_latest_clock_entry();
boost::thread Thread(&TimeEvent::wait, &timeEvent);
// boost::thread Thread1(boost::bind(&TimeEvent::wait, &timeEvent));
cout << "good" << endl;
timeEvent.update_system_time_on_startup();
Thread.join();
return 0;
}
1条答案
按热度按时间56lgkhnf1#
所以我想独立于main()运行wait()
你可以通过在一个单独的线程中运行wait来实现,当然你已经这样做了,而且你 * 可以 * 实际上已经在
main
中运行了其他代码,你已经这样做了,尽管很少:当
wait
在你的线程上运行的时候打印出来的。一切都很好。当然,如果你想做更多的事情,那就去做吧。一旦你join()
了Thread
,你的主线程就会阻塞,直到线程退出。让我来介绍一下我在代码审查期间发现的一些观察结果,然后给您一些关于后台线程的优雅关闭的想法。
第一部分观察
程序的行为与预期不符的一个原因是
get_latest_clock_entry()
中的Undefined Behavior:任何事情都有可能发生,但依赖条件
currentTime.tv_sec > ModifiedTime.tv_sec
肯定不可靠。此外,在时钟动态调整的系统中,基于时钟值进行等待可能不可靠,就像您的代码对
::clock_settime(CLOCK_REALTIME)
所做的那样。当然,正如所写的那样,代码的行为将不稳定,因为您确实使用具有 * 不确定值 * 的clock_settime
(如前所述)。在线程的开始和你的
update_system_time_on_startup
之间也有一个竞态条件。目前,显然它什么也不做(只是说"hello"),但是一旦它做了更多的事情(像它说的那样),它将(a)在没有同步的情况下接触共享状态(b)影响wait
的定时代码。receive_time_event
奇怪地忽略了这个参数。这是故意的吗?为什么是通过lvalue-reference传递的?它需要更新吗?建议
你可能应该更好地解释你实际上想达到的目标。
假设您尝试同步不同的系统时钟,如下所示
旨在每分钟一次:
这已经不符合问题中的问题描述。另外,您的等待代码应该
1.使用单调时钟以防止在改变时钟时出现错误
1.使用预先计算的最后期限,而不是盲目地在给定时间上增加60秒
1.我不太在意UTC与本地时间
让我们回顾并简化一些其他代码:
要消除争用条件,只需将
update_system_time_on_startup
移到timeEvent
类中,更好的是,将整个示例移到线程中!如前所述,等待代码过于复杂(清理版本):
它可以更简单,同时又是等价的:
注意,我们现在不再需要
posix_time
,也不需要链接到Boost Datetime库,事实上,我们可以用std::thread和std::filesystem替换boost::thread和boost::filesystem,并且be * 没有任何boost依赖性 *。当然,这里假设
validate()
不需要时间,或者后续的validates()
间隔超过60秒也没关系,坦白地说,在时间同步听起来很重要的情况下,这听起来很奇怪,所以我会写 * 我的意思 *,明确地使用一个单调的时钟:显然,定义适当的区间如下:
现场演示
本地:
额外奖励:正常关机
当然,您希望在合理的时间限制内正常关机:
BONUS2:使用加速线程中断点
这样做的优点是将TimeEvent示例封装在线程中,从而消除了手动同步的需要,缺点是需要Boost Chrono、Boost System、Boost Thread(在我的示例中,还需要Boost Filesystem,只是为了说明切换是多么容易):
你甚至可以让你永远不会忘记打断和加入: