Портирование InterlockedExchange с использованием только встроенных функций GCC - PullRequest
4 голосов
/ 25 ноября 2011

Windows API предлагает InterlockedExchange, который задает значение в памяти атомарно.Используя только встроенные функции GCC, я бы хотел создать эквивалент этой функции.Будет ли достаточно установки значения и последующего вызова барьера памяти (см. Код ниже)?

template <typename T>
T InterlockedExchange(volatile T& _data, T _value)
{
    const T oldValue = _data;
    _data = _value;
    __sync_synchronize();
    return oldValue;
}

Спасибо.

РЕДАКТИРОВАТЬ : Предлагаемый фрагмент НЕ является правильным решением проблемы, поскольку он явно не атомарный(но, ну, я должен был попробовать хотя бы).

Ответы [ 2 ]

9 голосов
/ 25 ноября 2011

Используйте __sync_val_compare_and_swap __sync_lock_test_and_set, а не __sync_synchronize.

Это имеет ту же функцию, что и InterlockedExchange.

Примерно так (непроверенный код!):

template<typename T> T InterlockedExchange(T& data, T& new_val)
{
    return __sync_lock_test_and_set(&data, new_val);
}

РЕДАКТИРОВАТЬ:
Ой, я прочитал неправильно, вы хотели InterlockedExchange, а не InterlockedCompareExchange ... так что __sync_lock_test_and_set (имя вводит в заблуждение-номер, но это именно то, что вы хотите).
См. здесь , внизу страницы.

0 голосов
/ 25 ноября 2011

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

...