Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我们是否需要以原子方式递增线程局部变量?_C++_Multithreading_Gcc_Thread Safety_Atomic - Fatal编程技术网

C++ 我们是否需要以原子方式递增线程局部变量?

C++ 我们是否需要以原子方式递增线程局部变量?,c++,multithreading,gcc,thread-safety,atomic,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, the

以下是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;
}
void*\uuucxa\u current\u primary\u exception()throw(){
//获取当前异常
__cxa_eh_globals*globals=uuucxa_get_globals_fast();
if(NULL==全局)
返回NULL;//如果没有全局变量,则不存在异常
__cxa_exception*exception_头=全局->caughtExceptions;
if(NULL==异常头)
返回NULL;//没有当前异常
如果(!isOurExceptionClass(&exception_头->unwindHeader))
return NULL;//无法捕获外部异常(无法对其进行重新计数)
if(isDependentException(&exception_头->unwindHeader)){
__cxa_相关_异常*dep_异常_头=
重新解释强制转换(异常头);
exception\u header=cxa\u exception\u from\u抛出的\u对象(dep\u exception\u header->primaryException);
}
void*抛出的对象=从异常(异常头)抛出的对象;
__cxa\u增量\u异常\u引用计数(抛出\u对象);
返回抛出的对象;
}
globals是线程本地存储变量,因此抛出的_对象也是特定于线程的。我的理解是抛出的对象是线程中抛出的异常-每个线程可能抛出自己的异常

但是函数_cxa_increment_exception_refcount()以原子方式执行增量-为什么?需要以原子方式执行增量的场景是什么?

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

std::exception_ptr
是一种类似指针的可空类型,用于管理已使用std::current_exception抛出和捕获的异常对象std::exception_ptr的实例可以传递给另一个函数,可能是在另一个线程上,在该线程中,可以重新调用异常并使用catch子句进行处理

std::exception\u ptr
是一个共享所有权智能指针

因为
std::exception_ptr
可以传递给另一个线程,所以参考计数器维护必须使用原子递增/递减


引用计数器嵌入到异常对象中,与
boost::intrusive_ptr
类似,与
std::shared_ptr
不同,谢谢,但我们需要原子增量时我没有得到。假设我们在一个工作线程中捕获了一个异常,并将其保存在一个全局std::exception_ptr中——在这个场景中我们需要原子增量吗?让我们进一步假设我们正在将保存的全局异常\u ptr传递到另一个线程-现在需要原子增量吗?@embedc,以防我们在工作线程中捕获异常并将其保存在全局
std::exception\u ptr
中时,工作线程可能有一个最终被销毁的本地副本,而另一个线程可能创建另一个副本全局计数器的副本,同时递增和递减同一参考计数器。这就是为什么引用计数器必须是线程安全的。Re,“globals是线程本地的…因此,
抛出的\u对象
也特定于线程。”我不知道LLVM的运行时支持库,也不知道
*抛出的\u对象
是否可以与其他线程共享,但是您不能仅仅从上面的代码示例中判断。
\uuucxa\u current\u primary\u exception()
函数通过跟随一系列指针来查找
*抛出的对象
,仅仅因为
全局变量本身是一个线程局部变量,这并不能证明它指向的对象没有共享,也不能证明链上其他对象的任何情况。