Нужно ли увеличивать локальную переменную потока атомарно? - PullRequest
5 голосов
/ 23 апреля 2019

Ниже приведена функция из libcxxabi от LLVM:

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 Ответ

2 голосов
/ 23 апреля 2019

Вы можете позвонить 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.

...