В новой стандартной операции атомарного приращения C ++ с предварительными условиями проверки перед увеличенным значением атомное значение было меньше указанного значения?
Могу ли я сделать это проще и быстрее, чем следующий код?
int atomic_inc(std::atomic_int& val, int less_than) {
int new_val;
int old_val = val.load();
do
{
if (old_val > less_than) return old_val;
new_val = old_val + 1;
} while (!val.compare_exchange_weak(old_val, new_val));
return new_val;
}
Если кто-то не знает, как это работает, сравните_exchange_weak:
compare_exchange_weak читает val, сравнивает со old_val и, если они не равны, сохраняет val в old_val. Если оно равно, сохраните new_val в val.
Нет, нет особой поддержки для увеличения значений меньше значения. Ваш код настолько эффективен, насколько вы можете получить. В C ++ 11 нет варианта без ожидания
Существует неограниченное количество возможных шаблонов «увеличения, если X». Производители оборудования решили, что единственное, что им нужно поддерживать — это «увеличение, если не изменение».
Теоретически вы могли бы изобрести аппаратную платформу со специальным ассемблерным кодом для нее, но C ++ 11 прямо не нацелен на это.
То, что я делал в прошлом, может сработать для вас, в зависимости от того, для чего вы это используете.
Если вы можете предположить, что val
не будете часто обрезать — так что возможная оптимизация отказа от использования CAS не сильно вас спасет — вы можете просто слепо увеличивать значение и корректировать его после прочтения:
int atomic_inc(std::atomic_int& val, int less_than) {
return std::min(++val, less_than);
}
А потом изредка клип val
вернуться к less_than
при необходимости, достаточно часто, чтобы вам не пришлось беспокоиться о int
переполнен, и ты золотой.
Если вы используете потоки, вы можете использовать mutex для атомарного приращения. Вот как вы это сделаете в этом случае:
Объявите и инициализируйте мьютекс глобально:
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL)
В одной теме:
int atomic_inc(std::atomic_int& val, int less_than) {
pthread_mutex_lock(&lock);
int newVal = val.load();
if (newVal < less_than)
newVal++
pthread_mutex_unlock(&lock);
return new_val;
}
Вам придется заблокировать и разблокировать мьютекс перед изменением val
в любой другой теме.
Для получения дополнительной информации о мьютексе: http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#SYNCHRONIZATION