2017-06-26 21 views
1

C++のアトミック操作として単一ビットを設定、クリア、テスト、フリップする方法はありますか?たとえば、 "compare_and_swap"のビット単位のバリアントです。アトミック性を保証したシングルビット操作

+0

'のstd :: atomic_bool'をチェックし、範囲エラーを追加する必要がありますか? – erip

+3

"C/C++"はありません。一つを選ぶ*。 –

+0

あなたはどのアーキテクチャを使用していますか?与えられたアーキテクチャがビットレベルのアトミック操作をサポートしていない場合、言語/コンパイラは魔法のようにそれを可能にしません。 –

答えて

3

ビットを整数で反転することは比較と交換の操作に過ぎません。これを使って1ビットをテストして反転させても何も変わらないということです。したがって、単純なcompare_exchange_weakループがこれを行います。

+0

を使用しているときは、期待される結果が分かっているものとみなされます。ビット操作ではそうではありません。 – chook

+1

C/C++の「アトミック」は、中断されないという意味でのアトミック操作と同じではなく、スレッド・セーフティの一定レベルを保証するだけであることに注意してください。たとえば、stdatomic.hはISRによって割り込み可能なカーネルコードには適していません。 https://stackoverflow.com/questions/19900524/does-the-c-11-standard-guarantees-that-stdatomic-is-implemented-as-an-atom –

+0

@chookを読むことはできません。期待される結果を決定する? – xaxxon

3

操作ビットは、compare_exchange RMWを必要とし、atomic変数の他のビットに触れないようにします。 ビットのテストは変更操作ではないため、load()で十分です。

あなたは

template<typename T, typename OP> 
T manipulate_bit(std::atomic<T> &a, unsigned n, OP bit_op) 
{ 
    static_assert(std::is_integral<T>::value, "atomic type not integral"); 

    T val = a.load(); 
    while (!a.compare_exchange_weak(val, bit_op(val, n))); 

    return val; 
} 

auto set_bit = [](auto val, unsigned n) { return val | (1 << n); }; 
auto clr_bit = [](auto val, unsigned n) { return val & ~(1 << n); }; 
auto tgl_bit = [](auto val, unsigned n) { return val^(1 << n); }; 


int main() 
{ 
    std::atomic<int> a{0x2216}; 

    manipulate_bit(a, 3, set_bit); // set bit 3 

    manipulate_bit(a, 7, tgl_bit); // toggle bit 7 

    manipulate_bit(a, 13, clr_bit); // clear bit 13 

    bool isset = (a.load() >> 5) & 1; // testing bit 5 
} 
+0

良い;私は 'val val 'を返すでしょう。 – Yakk

+0

同意する。実際には、原子操作が従う設計規約に近い – LWimsey

関連する問題