简体   繁体   English

C++ 线程等效于 pthread_exit

[英]C++ thread equivalent of pthread_exit

I need a C++ equivalent of pthread_exit in order to make a function that when called cause the calling thread to exit.我需要一个等效于pthread_exit的 C++ 来制作一个 function ,当调用它时会导致调用线程退出。

In C, using pthreads.h I simply called pthread_exit .在 C 中,使用pthreads.h我简单地调用了pthread_exit I'm new to C++ and need to use its <thread> for which I cannot find a similar function.我是 C++ 的新手,需要使用它的<thread> ,我找不到类似的 function。

I'm using C++17, and the code has to compile on Linux (and possibly on MacOs).我正在使用 C++17,代码必须在 Linux 上编译(可能在 MacOs 上)。

There's no direct way to do this - the normal way to terminate a thread is to return from the top-level function that is called when the thread starts up - but you can achieve the same effect by throwing an exception at the point where you wish to terminate the thread and catching it in the thread's top-level function.没有直接的方法可以做到这一点 - 终止线程的正常方法是从线程启动时调用的顶级 function 返回 - 但您可以通过在您希望的点抛出异常来实现相同的效果终止线程并在线程的顶级 function 中捕获它。 This has the advantage that the thread's stack is correctly unwound and any relevant destructors get called.这样做的好处是线程的堆栈被正确展开并且任何相关的析构函数都被调用。

For example:例如:

#include <iostream>
#include <thread>
#include <exception>

class thread_exit_exception : public std::exception {};

void thread_subfunc ()
{
    std::cout << "Entering thread_subfunc\n";
    thread_exit_exception e;
    throw e;
    std::cout << "Leaving thread_subfunc (never executed)\n";
}

void thread_func ()
{
    std::cout << "Entering thread_func\n";
    try
    {
        thread_subfunc ();
    }
    catch (const thread_exit_exception&)
    {
    }
    std::cout << "Leaving thread_func\n";
}

int main()
{
    std::cout << "Entering main\n";
    std::thread t = std::thread (thread_func);
    t.join ();
    std::cout << "Leaving main\n";
}

Output: Output:

Entering main
Entering thread_func
Entering thread_subfunc
Leaving thread_func
Leaving main

Live demo现场演示

C++ is more reliant on its call stack than C is. C++ 比 C 更依赖其调用堆栈。 C++ programs often use RAII, which means that resources are bound to objects that frequently live on the stack. C++ 程序经常使用 RAII,这意味着资源绑定到经常存在于堆栈上的对象。 Users of such objects expect those objects to be destroyed properly.此类对象的用户期望这些对象被正确销毁。 If a function creates a stack object, it expects that at some point in the future, control will return to that function and the stack object will be destroyed. If a function creates a stack object, it expects that at some point in the future, control will return to that function and the stack object will be destroyed.

As such, there is no mechanism for a thread with some stack depth to simply go away.因此,没有机制让具有一定堆栈深度的线程简单地离开 go。 A std::thread only ends when the end of the function passed to the thread constructor is reached (an exception emitted from a thread function invokes std::terminate ). std::thread仅在到达传递给thread构造函数的 function 的末尾时结束(从线程 function 调用std::terminate发出的异常)。

Given this, it is best to restructure your code so that you never need to cause a thread function to exit from some arbitrary place in the call graph.鉴于此,最好重新构建您的代码,以便您永远不需要导致线程 function 从调用图中的某个任意位置退出。 Make it so that the only points where you would want the current thread to exit are places within the thread's main function.使您希望当前线程退出的唯一点是线程的主 function 内的位置。

For example, the typical way a thread pool works is that each thread's main function goes to sleep, waiting on some form of task to be dropped off for that thread.例如,线程池的典型工作方式是每个线程的主 function 进入睡眠状态,等待某种形式的任务被该线程丢弃。 When a task is available, it executes that task.当任务可用时,它会执行该任务。 Upon the task's completion, it checks for a new task, and if none is available, it goes back to sleep until a task is ready.任务完成后,它会检查是否有新任务,如果没有可用的,它会重新进入睡眠状态,直到任务准备好。

In such a thread pool, no thread ever stops .在这样的线程池中,没有线程会停止 Individual tasks stop, but the actual std::thread is eternal (or at least, lives as long as the pool).单个任务停止,但实际的std::thread是永恒的(或者至少与池一样长)。

If a task needs to terminate, then such termination essentially represents a failure to perform the task.如果一个任务需要终止,那么这种终止本质上就代表了该任务的执行失败。 In C++, that's spelled "throwing an exception".在 C++ 中,拼写为“抛出异常”。 The main thread would put all task invocations in a try block, with a catch block for the specific exception type.主线程会将所有任务调用放在一个try块中,并带有一个用于特定异常类型的catch块。 It can then report to whomever that a task failed, then go check for a new task.然后它可以向任何人报告任务失败,然后 go 检查新任务。

And this makes sure that the task's call stack is cleaned up.这可以确保清理任务的调用堆栈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM