Атомика и `errno`: разумно ли использовать атомы C ++ 11 для чтения защищенного значения errno?

Обработка errno — это одна из проблем использования POSIX API в многопоточной среде. Было бы разумно использовать блокировку, используя std::atomic как следующий?

class FastLock{
std::atomic_int value;
public:
FastLock()
: value{0}{}

void unlock()
{
value.store(0,std::memory_order_release);
}

bool try_lock()
{
int r = value.exchange(1,std::memory_order_acquire);
return !r;
}
};

Контекст будет похож на это:

template<typename function, typename ...args>
auto shield(function _fn){
static FastLock* lk = new FastLock{};
return [=](args... _v){
while(lk->try_lock());
auto ret = std::forward(_fn, _v...);
auto errval = errno;
lk->unlock();
return std::make_pair(ret,errval);
};
}

Приведет ли это к какому-либо неопределенному поведению или поведению, определяемому реализацией?

-2

Решение

В то время как старый стандарт POSIX 1988 года требовал errno быть глобальным объектом, это больше не относится к последующим версиям. По крайней мере POSIX.1-2001 требует errno быть местным потоком. Я подозреваю, что это уже требовалось POSIX.1c-1995, который определяет потоки POSIX, но у меня нет доступа к этому документу, поэтому я не могу проверить.

Я не ожидал бы, что система POSIX, которая поддерживает C ++ 11, также не будет поддерживать POSIX 2001, и поэтому использование атомных элементов C ++ 11 кажется маловероятным.

Тем не менее, в то время как стандарт C не требует errno чтобы быть глобальным объектом (по крайней мере, C99 не), он также не гарантирует локальность потока errno, Итак, блокировка errno может быть необходимо в не POSIX-системах или старых POSIX-системах, которые не обеспечивают локальность потоков. И если по какой-то причине платформа поддерживает C ++ 11, то атомарность C ++ 11 может быть идеальным выбором для реализации блокировки — или не может быть. По крайней мере, в теории.

Обратите внимание, что для обеспечения безопасности потока вы должны убедиться, что все вызовы функций, которые могут установить errno должен использовать замок. Если вы используете какие-либо библиотеки, которые могут использовать такие стандартные функции, вы также должны блокировать вызовы для таких функций.

3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector