Если вы хотите получить старое значение x и значение a не изменилось, используйте (xa) в качестве старого значения:
fetch_and_add(int *x, int a) {
#pragma omp atomic
*x += a;
return (*x-a);
}
ОБНОВЛЕНИЕ: на самом деле это не был ответ, потому что x можно изменить послеатомный другой поток.Таким образом, кажется невозможным сделать универсальное «извлечение и добавление» с помощью OMP Pragmas.Под универсальной я подразумеваю операцию, которую можно легко использовать из любого места кода OMP.
Вы можете использовать omp_*_lock
функции для имитации атомики:
typedef struct {omp_lock_t lock;int value;} atomic_simulated_t;
fetch_and_add(atomic_simulated_t *x, int a)
{
int ret;
omp_set_lock(x->lock);
x->value +=a;
ret = x->value;
omp_unset_lock(x->lock);
}
Это уродливо и медленно (выполнение 2 атомных операций вместо 1).Но если вы хотите, чтобы ваш код был очень переносимым, он будет не самым быстрым во всех случаях.
Вы говорите «как следующее (только без блокировки)».Но в чем разница между «неблокирующими» операциями (с использованием префикса «LOCK» процессора, или LL / SC или т. Д.) И операциями блокировки (которые реализуются с помощью нескольких атомарных инструкций, цикла занятости для короткого ожидания разблокировки и спящего режима ОСдолго ждет)?