Потребовалось реализовать потоково и переполнительно безопасный счетчик на std::atomic
. Сделал вот так, как и многие в интернете:
template<typename T, T COUNT_MIN = std::numeric_limits<T>::min()
, T COUNT_MAX = std::numeric_limits<T>::max() >
T SafeIncrement(std::atomic<T> & counter)
{
static_assert(MIN < MAX, "range wrong");
T current = counter.load();
T result = current == COUNT_MAX ? COUNT_MIN : current + 1;
while(!counter.compare_exchange_strong(current, result))
{
result = current == COUNT_MAX ? COUNT_MIN : current + 1;
}
return result;
}
Но у меня возникло подозрение, не возникнет ли здесь гонок. При интенсивном почти непрерывном вызове SafeIncrement
из параллельных потоков, не возможна ли ситуация когда отдельные потоки будут вечно (или надолго!) промахиваться с обменом пусть и атомарном?
Поясню о чем речь. Гонка была бы невозможна если бы потоки выполняли обмен строго экслюзивно и по-очередеи. Например, если они исполняются псевдопараллельно на одном вычислителе или такой механиз обеспечивает ОС. У нас же гарантируется только экслюзивность, а не очередность.
Так вот, на эту тему что-то предусмотрено в реализациях std::atomic
? Или есть правильные решения?
Нет, такая ситуация невозможна. Потому что каждая ошибка обмена означает что какой-то другой поток успешно этот самый обмен совершил. Таким образом, на каждой итерации цикла уменьшается число конкурирующих потоков - а значит, рано или поздно они закончатся (если только по какой-то причине не прибывают быстрее чем убывают).
Однако, значительное замедление при одновременном доступе из разных потоков действительно возможно, поэтому таких переменных стоит избегать.
PS Ваше решение мне кажется каким-то переусложненным: можно же просто использовать беззнаковые целочисленные типы, у них переполнение не вызывает UB.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Не могу понять как происходит взаимодействие модели и представленияНужно добавить элемент в модель и установить для него виджет в отображении
Хочу закрасить окно узором битмапа, который грузится из ресурсов и помещается в кистьНе могу понять какие лучше функции использовать и с чего...
Подскажите, пожалуйста, какую оптимизацию проведет компилятор в таком коде: