Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we need to increment thread-local variable atomically?

Below is a function from LLVM's 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 is a thread-local storage variable, and therefore the thrown_object is also specific for a thread. My understanding is that thrown_object is an exception thrown in a thread - each thread may throw its own exception.

But the function __cxa_increment_exception_refcount() performs increment atomically - why? What's the scenario that requires increment to be performed atomically?

like image 731
embedc Avatar asked Oct 27 '22 15:10

embedc


1 Answers

You can call std::current_exception and get a smart-pointer to the exception:

std::exception_ptr is a nullable pointer-like type that manages an exception object which has been thrown and captured with std::current_exception. An instance of std::exception_ptr may be passed to another function, possibly on another thread, where the exception may be rethrown and handled with a catch clause.

...

std::exception_ptr is a shared-ownership smart pointer.

Because std::exception_ptr can be passed to another thread the reference counter maintenance must use atomic increment/decrement.

The reference counter is embedded into the exception object, like for boost::intrusive_ptr and unlike std::shared_ptr.

like image 119
Maxim Egorushkin Avatar answered Nov 16 '22 12:11

Maxim Egorushkin