2015-11-04 5 views
0

У меня есть структура в союзе с uint64_t, обеспечивающая доступ к двум int32_t. Я хотел бы уменьшить один из элементов структуры атомарно. Я пришел с этим:Атомно декремент данных члена союза?

class{ 

public: 

void atomicallyDecrement_B(const int32_t decrementByThisValue){ 
    MyUnion newUnion; 
    MyStruct currentStruct = _union._data; 

    do{ 
     const int32_t currentB = currentStruct.b; 
     const int32_t currentA = currentStruct.a; 
     const int32_t newB = currentB - decrementByThisValue; 

     newUnion._data.a = currentA; 
     newUnion._data.b = newB; 
    } 
    while(!std::atomic_compare_exchange_weak(&_union._data, &currentStruct, newUnion._data)); 
} 

private: 
    struct MyStruct{ 
     int a; 
     int b; 
    }; 

    union MyUnion{ 
     MyUnion(){ 
      _data.a = 0; 
      _data.b = 0; 
     } 

     MyStruct _data; 
     uint64_t _atomic; 
    } _union; 
}; 

но это, кажется, первый аргумент atomic_compare_exchange_weak() должен быть сам атомный тип. Есть ли способ выполнить эту операцию без, изменяя член данных uint64_t равным std::atomic<uint64_t>?

Я использую GCC 5.2

+1

Вы не можете атомарно доступ к не -атомный тип данных. Если вы не хотите, чтобы он был атомарным, вам лучше защищать доступ с помощью блокировки. – Brian

+0

Существуют нестандартные способы сделать это - каждая среда компилятора/сборки создала свой собственный, прежде чем атом появился в стандарте. Если это поможет, укажите, какой компилятор вы используете и на какой платформе вы работаете. –

+0

@DaleWilson компилятор специфичен, я использую GCC 5.2 – user997112

ответ

1

GCC имеет атомные операции как встроенные. Они описаны на странице this page.

Операцию вы ищете

type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) 

или

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) 

Эти встроенные команды выполняют атомное сравнения и замены. То есть, если текущее значение * ptr является oldval, тогда напишите newval в * ptr.

Для пользователей Windows, соответствующая возможность является

LONG __cdecl InterlockedCompareExchange(
    _Inout_ LONG volatile *Destination, 
    _In_ LONG   Exchange, 
    _In_ LONG   Comparand 
); 

который описан here

Примера использования Ей формы НКИ присущим:

do{ 
    int oldVal = protectedVal; 
    int newVal = someFunction(oldVal); 
} while (__sync_bool_compare_and_swap(&protectedVal, oldVal, newVal); 
+0

Я правильно понял, что GCC-свойство не копирует неожиданное значение во второй/третий аргумент, если ожидаемое значение не найдено в «атомарном»? – user997112

+0

Он возвращает значение из * ptr перед свопом. Вы можете сравнить его с oldval, чтобы узнать, работает ли swap. Существует еще один метод, который возвращает bool, чтобы указать, произошел ли обмен. Это не дает вам значение «раньше». Я отредактировал свой ответ, чтобы предоставить пример кода. –

1

Да, есть способы, чтобы сделать это. Вы можете использовать атомные встроенные генераторы GCC, найденные здесь: https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html или вы можете использовать атомные функции, предоставляемые вашей ОС. Третий вариант - использование инструкций по атомной сборке.

 Смежные вопросы

  • Нет связанных вопросов^_^