gpt4 book ai didi

c++ - 干净取消在输入/输出调用时阻塞的 std::thread

转载 作者:行者123 更新时间:2023-11-30 05:14:05 28 4
gpt4 key购买 nike

我有一个 std::thread 可能会在文件描述符输入/输出调用时被阻塞,我该如何彻底取消它?

考虑以下示例:

#include <unistd.h>
#include <thread>

void thread_routine(int fd)
{
char buf;
read(fd, &buf, 1);
}

int main()
{
int pipefd[2];
pipe(pipefd);

std::thread thread(&thread_routine, pipefd[0]);

thread.join();

close(pipefd[0]);
close(pipefd[1]);
}

join() 之前我可以做什么来确保它不会永远锁定? (管道只是获取文件描述符的快速示例方法,我有一个 more exotic scenario 但我正在尝试获得一个通用的答案。)

使用 pthreads 我可以调用 pthread_cancel() 因为 read()write() 是取消点,但是没有 C++ 方法来取消 std::thread(我可以获得 thread::native_handle() 并将其传递给 pthread_cancel(),但我会就像一种更清洁的方法)。

请注意:

  • 我无法在非阻塞模式下设置文件描述符
  • 我不能在文件描述符上使用 select()

最佳答案

使用 std::future ,您可以在有限的时间间隔内阻塞并最终决定停止等待并分离线程。如果您无论如何都要退出,泄漏正在运行的线程并不重要。如果不退出,那么阻塞调用将自然返回并且线程将被销毁,或者无论如何它将在进程的剩余生命周期内被阻塞。

在以下示例中,MAX_WAIT_TIME 用作分离和退出的条件。

#include <chrono>
#include <future>
#include <thread>

using namespace std::literals;

const auto BLOCK_DURATION = 100ms;
const auto MAX_WAIT_TIME = 3s;

int main() {
// Some blocking call.
auto blocking_call = [] { std::this_thread::sleep_for(1min); };

// Wrap the callable in a packaged task and get future.
std::packaged_task<void()> task{blocking_call};
auto future = task.get_future();

auto start_time = std::chrono::steady_clock::now();
std::thread t{std::move(task)};

// Continually check if task is finished, i.e., if blocking call has returned.
auto status = future.wait_for(0s);
while (status != std::future_status::ready) {
status = future.wait_for(BLOCK_DURATION);

// Room for condition to stop blocking, e.g., check some signaling etc.
auto duration = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start_time);
if (duration > MAX_WAIT_TIME) {
break;
}
}

if (status == std::future_status::ready) {
future.get(); // Optionally get return value.
t.join();
} else {
t.detach();
}

/* And we're on our way... */
}

std::future::wait_for将在调用返回时立即返回,即使完整的等待时间尚未过去。

如果 time 是调用可能阻塞的时间限制,那么甚至还有整洁的 std::future::wait_until . 例如:

auto start_time = std::chrono::steady_clock::now();
std::thread t{std::move(task)};

auto status = future.wait_until(start_time + MAX_WAIT_TIME);

if (status == std::future_status::ready) {
t.join();
} else {
t.detach();
}

关于c++ - 干净取消在输入/输出调用时阻塞的 std::thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43577112/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com