Синхронизация C ++ 0x одновременна, необходим ли забор - PullRequest
3 голосов
/ 09 апреля 2011

Недавно я задал несколько вопросов об атомарности и C ++ 0x, и я хотел бы убедиться, что понимаю семантику упорядочения, прежде чем преобразовывать какой-либо код.Допустим, у нас есть код пре-0x:

atomic_int a = 0;
some_struct b;

Thread A:
b = something;
atomic_store_fence();
a = 1;

Thread B:
if( a == 1 )
{
  atomic_load_fence();
  proc(b);
}

Использование того, что предлагает вам текущий компилятор / платформа для atomic_int, atomic_store_fence и atomic_load_fence.

В C ++ 0x код имеет несколько возможных форм.Два очевидных из них выглядят следующим образом:

atomic<int> a = ATOMIC_VAR_INIT(0);
some_struct b;

Thread A:
b = something;
atomic_thread_fence( memory_order_release );
a.store( 1, memory_order_relaxed );

Thread B:
if( a.load( memory_order_relaxed ) == 1)
{
  atomic_thread_fence( memory_order_acquire );
  proc(b);
}

или

Thread A:
b = something;
a.store( 1, memory_order_release );

Thread B:
if( a.load( memory_order_acquire ) == 1)
{
  proc(b);
}

Правильно ли я прочитал, что атомарная последовательность освобождения / загрузки-получения представляет собой синхронизируется событие, которое имеет те же значения порядка памяти, что и явная версия забора?То есть, верна ли вторая версия?

Если верна, то вторая выдает забор больше, чем необходимо: даже когда a != 1.Раздел 29.8-3 стандарта указывает, что я могу смешивать и сочетать атомные элементы и ограждения.Таким образом, является ли приведенная ниже корректная и разумная реализация?

Thread A:
b = something;
a.store( 1, memory_order_release );

Thread B:
if( a.load( memory_order_relaxed ) == 1 )
{
  atomic_thread_fence( memory_order_acquire );
  proc(b);
}

1 Ответ

5 голосов
/ 10 апреля 2011

Да, ваше понимание верно, и да, окончательный список является разумной реализацией.

Обратите внимание, что ATOMIC_VAR_INIT в основном предоставляется для совместимости с C1X, в C ++ 0x вы можете просто написать:

std::atomic<int> a(0);
...