在另一个线程中独立计时For循环的每个Tick的最佳方法



假设我有一个客户端线程和一个服务器线程。客户端线程必须执行昂贵的for循环操作,这很容易挂起。因此,服务器必须独立地确定for循环的每个刻度是否超过了最大时间。这背后的上下文是,如果客户端花费太长时间来完成一个标记,服务器将使客户端超时。

我最初的想法是在客户端和服务器线程中有两个for循环。服务器线程将有一个等待1秒的条件变量。如果客户端没有在1秒内通知条件变量,服务器将超时:

服务器

bool success;
for (int i = 0; i < 10; i++) {
std::unique_lock<std::mutex> lock(CLIENT_MUTEX);
success = CLIENT_CV.wait_for(lock, std::chrono::seconds(1));
if (!success) {
std::cout << "timed out during tick " << i << std::endl;
break;
}
}

客户

for (int i = 0; i < 10; i++) {
std::unique_lock<std::mutex> lock(CLIENT_MUTEX);
//do work
CLIENT_CV.notify_one();
}

然而,我的实现尝试是不可靠的,并且在给定客户端相同工作的随机时间超时。我怎样才能改进设计使其更可靠?

注:

一个简单的解决方案是让服务器对整个for循环计时,而不是对每个tick计时。但是,如果for循环在10次中的第1次失败,并且计时器等待10秒,那么客户机将在10秒后得到通知。但是,如果服务器为每个tick (10x1sec = 10secs)强加1秒超时,那么客户端将被通知超时,而不必等待整整10秒。

编辑。

整个客户机/服务器/超时类比只是将问题置于上下文中。我只对从另一个线程计时for循环的最佳方法感兴趣。

可以这样做:

共享var:

std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> ledger;
std::mutex ledger_mtx;

客户:

for (int i = 0; i < 10; i++) {
{
std::scoped_lock lock(ledger_mtx);
ledger.push_back(std::chrono::high_resolution_clock::now());
}
// Do work
}
{
std::scoped_lock lock(ledger_mtx);
ledger.push_back(std::chrono::high_resolution_clock::now());
}

服务器:

size_t id = 0;
std::this_thread::wait_for(1s); // Some time so that initial write to ledger is made
while(true) {
{
std::scoped_lock lock(ledger_mtx);
if(ledger.size()==id) { /* Do something if the thread hangs */ }
id = ledger.size();
std::chrono::time_point<std::chrono::high_resolution_clock> last_tick = ledger.back();
}
if(id == 11) break;
std::this_thread::sleep_for(1s - (std::chrono::high_resolution_clock::now() - last_tick));
}

这样就可以对线程进行计时,同时从外部监视它。这是最好的方法吗?也许不是,但它确实给了你你需要的时间。

最新更新