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

Best approach to Independently Timing each Tick of a For Loop in another Thread

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

我下面的初步想法是在客户端和服务器线程中有两个 for 循环。服务器线程将有一个等待 1 秒的条件变量。如果客户端每tick 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 秒后收到通知。但是,如果服务器为每个滴答 (10x1sec = 10secs) 施加 1 秒超时,则客户端将被通知超时,而无需等待整整 10 秒。

编辑。

整个client/server/timeout类比只是将问题放在上下文中。我纯粹对从不同线程为 for 循环计时的最佳方式感兴趣。

一种方法可能是:

共享变量:

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));
}

这样您可以在从外部监视线程的同时为线程计时。这是最好的方法吗?可能不会,但它确实为您提供了所需的时间。