Как я могу получить доступ к 32- или 64-битному целочисленному значению, подобному sync_fetch_and_add в GCC в методе CONST?

Я привык использовать мьютексы pthread и т. Д. (Или повышающие эквиваленты) для синхронизации / защиты доступа к общим для потоков данным.

Совсем недавно мне пришлось работать с кодом, в котором атомарность используется в некоторых местах, чтобы избежать некоторых издержек блокировки мьютекса и т. Д. В целях этого вопроса я спрашиваю больше о том, КАК это сделать, а не о том, Стоит делать 😉

Код скомпилирован с GCC 4.4.7, iir и на Linux x86-64.
Я часто сталкивался с подобными звонками: InterlockedCopy(variable)

который определен как

__sync_fetch_and_add(&(__var__), 0)

Теперь, кажется, это хорошо отвечает всем требованиям, за исключением того, что у меня есть привычка желать, чтобы методы, которые НЕ МОДИФИЦИРУЮТ члена, были … постоянными.

Итак, если у меня есть переменная флага «status», которую я использую, в настоящее время это uint32_t (но я хочу изменить типы или использовать typedef sig_int_t и т. Д.), И я хочу установить для нее какое-либо значение enum в одном потоке и прочитать его в другом через средство доступа const, как я могу сделать это, не делая средство доступа неконстантным или не делая изменяемый элемент доступа?

Простите за мое невежество, но я подумал: в GCC много атомных примитивов. Включая значения для предварительного или последующего добавления, вычитания, и, или, и т. Д. Значений и возвращая их атомарно (с включенным полным барьером памяти) — почему нет:

__sync_fetch(__var__) built-in.

Это потому что не нужно. То, что мы можем просто использовать обычный uint32_t и:

T1(CPU0): __sync_synchronize(); statusFlag = ENUM_VALUE;

T2(CPU1): if (statusFlag == ENUM_VALUE)
{ // do stuff ... }
__sync_synchronize();

Или какой-то такой-то
1. Обеспечивает атомарный доступ к правильно выровненным интегральным переменным.
2. Гарантирует, что когда флаг обновляется в одном потоке, метод, который проверяет этот флаг (не в цикле) в другом потоке, будет видеть его в следующий раз, когда он проверяет этот флаг в другом потоке (с учетом времени для согласованности). «вещи», о которых я пытаюсь узнать — случиться …)

(так сложно набрать этот вопрос не в интерактивном режиме;) — извините)

В основном, я не могу себе представить, что GCC пропустил простую не мутирующую «выборку» если это было потому, что это явно не нужно, поскольку это достижимо тривиально с помощью других существующих средств.

0

Решение

Линия __sync_fetch_and_add(&(__var__), 0) на самом деле делает что-то немного другое, чем просто получить переменную. Требуется владение строкой кэша. Я не уверен, что это задумано, но это то, что он делает. Таким образом, изменение его изменит семантику программы.

Архитектура x86-64 строго упорядочена, поэтому вам, как правило, не нужно беспокоиться о переупорядочении памяти, кроме компилятора.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector