2013-05-23 14 views
7

私は疑問に思っていましたが、プリミティブなデータ型はC++ 11ではstd :: atomicと宣言できますか?ライブラリクラスオブジェクトを "アトミックに"突然変異させたりアクセスしたりすることを宣言することは可能でしょうか?例えばC++ 11プリミティブデータ型のみをアトミックに宣言できますか?

これらのsetterメソッドとgetterメソッドが異なるスレッドで呼び出された場合、私は、

using namespace std::chrono; 
time_point<high_resolution_clock> foo; 

// setter method 
void set_foo() { 
    foo = high_resolution_clock::now(); 
} 

// getter method 
time_point<high_resolution_clock> get_foo() { 
    return foo; 
} 

を持っているかもしれませんが、私は未定義の動作を引き起こすかもしれないと思います。私がfooを次のように宣言することができればいいと思います。fooのすべての操作はアトミックなやり方で行われるようになります。私のプロジェクトのためのアプリケーションでは、数十のクラスにまたがって宣言されたfoo変数が数百にも及ぶことがあります。宣言とlock_guardの代わりにオブジェクトを変更して「原子」にアクセスする方がはるかに便利だと思います場所全体にミューテックス。

これはできないのですか、それとも良い方法がありますか、本当にどこでもmutexとlock_guardを使用する必要がありますか?

更新

  • 任意の受験者?私はまともな情報のためにウェブ上で釣りをしてきましたが、原子を使っている例はあまりありません。適用できる範囲を確かめることはできません。
+0

std :: atomicは、壊れたスレッドコードの回避策ではありません。別のスレッドがセッターを呼び出すと、最初に呼び出されたスレッドがゲッターからガベージ値を取得します。 –

答えて

3

atomic<>は、プリミティブ型に限定されない。 atomic<>のタイプTtrivially copyable)を使用することができます。セクションから29.5アトミック・タイプC++ 11標準(それはまたstd::atomicで計上)の

原子ジェネリッククラステンプレートがあります。テンプレート引数Tの型は単純にコピー可能(3.9)でなければならない。

原子アクセスが必要とされるオブジェクトは、元のオブジェクトとstd::mutexを含む、新しいオブジェクトを定義し、次いでatomic<>で使用することができない場合。これは、lock_guard<>が新しいスレッドセーフオブジェクトのgetterとsetter内でのみ使用され、コード全体には散らばらないことを意味します。 templateは、必要なスレッドの安全性の機械を定義することができるかもしれない:

template <typename T> 
class mutable_object 
{ 
public: 
    mutable_object() : t_() {} 
    explicit mutable_object(T a_t) : t_(std::move(a_t)) {} 
    T get() const 
    { 
     std::lock_guard<std::mutex> lk(mtx_); 
     return t_; 
    } 
    void set(T const& a_t) 
    { 
     std::lock_guard<std::mutex> lk(mtx_); 
     t_ = a_t; 
    } 
private: 
    T t_; 
    mutable std::mutex mtx_; 
}; 

using mutable_high_resolution_clock = 
     mutable_object<std::chrono::time_point< 
      std::chrono::high_resolution_clock>>; 

using mutable_string = mutable_object<std::string>; 

mutable_high_resolution_clock c; 
c.set(std::chrono::high_resolution_clock::now()); 
auto c1 = c.get(); 

mutable_string s; 
s.set(std::string("hello")); 
auto s1 = s.get(); 
0

アトミックスは自明コピー可能なクラス(と、メンバーも自明コピー可能です何のカスタムコピーコンストラクタを持っていない、すなわちクラス)に限定されています。

この要件は、アトミックのための巨大な利点があります。コンストラクタは

  • すべてアトミックにデータをコピーするためにロック(スピンロックやミューテックス)とのmemcpyでモデル化することができ投げたので

    • ノーアトミック操作を投げることができます。
    • すべてのアトミックには有限の実行時間(制限付き)があります。

    アトミックは時々スピンロックを使用して実装されるため、スピンロックを保持しながら無制限のタスクを避けることが強く求められています。いずれかのコンストラクタが許可されていれば、非常に小さなクリティカルセクションのスピンロックよりも遅いフルブローミューテックスで実装をフォールバックする必要があります。

  • 関連する問題