GCC組み込み関数のみを使用してInterlockedExchangeを移植する

Windows APIは、メモリ内の値をアトミックに設定する InterlockedExchange を提供します。 GCC組み込み関数のみを使用して、私はその関数と同等のものを作りたいと思います。値を設定してメモリバリアを呼び出すだけで十分です(下記のコードを参照してください)?

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

ありがとうございました。

EDIT: The proposed snippet is NOT a correct solution to the problem, as it is clearly not atomic (but, well, I had to give a try at least).

4
変更、ありがとう:)
追加された 著者 qdii,
_data パラメータは参照として宣言しますが、後でポインタ逆参照を使用してアクセスします。
追加された 著者 Some programmer dude,

2 答え

__ sync_synchronize ではなく __ sync_val_compare_and_swap __ sync_lock_test_and_set を使用してください。

これは、InterlockedExchangeとまったく同じ機能を持っています。

このようなもの(テストされていないコード!):

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

EDIT:
Oi, I read wrong, you wanted InterlockedExchange, not InterlockedCompareExchange ... so that is __sync_lock_test_and_set (the name is a misleading Intel-nomer, but it's exactly what you want).
See here, bottom of the page.

9
追加された
__ sync_lock_test_and_set()はAcquireセマンティクスしか持たないので、これは InterlockedExchangeAcquire()のみに相当します。 InterlockedExchange()と同等の完全なメモリバリアに __ sync_synchronize(); を追加する必要があります。
追加された 著者 caf,

提案された例は、アトミックではないため、等価ではありません。あなたの関数を実行する2つのレーススレッドは、新しい値の1つが「失われている」という、同じ古い値を取得することができます。

0
追加された
確かに、私は解決策を見つけるとすぐに変更します:)
追加された 著者 qdii,