我们是否需要原子地递增线程局部变量?

时间:2019-04-23 11:05:27

标签: c++ multithreading gcc thread-safety atomic

以下是LLVM的libcxxabi中的函数:

void *__cxa_current_primary_exception() throw() {
    //  get the current exception
    __cxa_eh_globals* globals = __cxa_get_globals_fast();
    if (NULL == globals)
        return NULL;        //  If there are no globals, there is no exception
    __cxa_exception* exception_header = globals->caughtExceptions;
    if (NULL == exception_header)
        return NULL;        //  No current exception
    if (!isOurExceptionClass(&exception_header->unwindHeader))
        return NULL;        // Can't capture a foreign exception (no way to refcount it)
    if (isDependentException(&exception_header->unwindHeader)) {
        __cxa_dependent_exception* dep_exception_header =
        reinterpret_cast<__cxa_dependent_exception*>(exception_header);
        exception_header = cxa_exception_from_thrown_object(dep_exception_header->primaryException);
    }
    void* thrown_object = thrown_object_from_cxa_exception(exception_header);
    __cxa_increment_exception_refcount(thrown_object);
    return thrown_object;
}

globals是线程局部存储变量,因此thrown_object也特定于线程。我的理解是thrown_object是在线程中引发的异常-每个线程都可以引发自己的异常。

但是函数__cxa_increment_exception_refcount()自动执行增量操作-为什么?在什么情况下需要增量执行原子操作?

1 个答案:

答案 0 :(得分:2)

您可以调用std::current_exception并获得指向异常的智能指针:

  

std::exception_ptr是一种可为空的指针式类型,用于管理已用std :: current_exception抛出并捕获的异常对象。 std::exception_ptr的实例可能会传递到另一个函数(可能在另一个线程上),在该线程中,异常可能会被重新抛出并通过catch子句进行处理。

     

...

     

std::exception_ptr是共享所有权智能指针。

由于std::exception_ptr可以传递给另一个线程,因此引用计数器维护必须使用原子增量/减量。

参考计数器被嵌入到异常对象中,就像boost::intrusive_ptr一样,与std::shared_ptr不同。