7

C++ 11 で std::atomic を宣言できるのはプリミティブ データ型だけですか? たとえば、ライブラリ クラス オブジェクトを「原子的に」変更またはアクセスするように宣言することは可能ですか?

たとえば、私は持っているかもしれません

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 を次のように宣言できればいいのですが。

std::atomic<time_point<high_resolution_clock>> foo;

... foo に対するすべての操作がアトミックな方法で実行されるようにします。私のプロジェクトのアプリケーションでは、数十のクラスで宣言された数百のそのような foo 変数が存在する可能性があり、宣言して lock_guard する代わりに、いわば「アトミック」にオブジェクトを変更してアクセスする方がはるかに便利だと思います。いたるところにミューテックス。

これは不可能ですか、それともより良いアプローチがありますか、それともミューテックスと lock_guard をどこでも使用する必要がありますか?

更新

  • テイカーはいますか?私は適切な情報を得るために Web で釣りをしてきましたが、atomic を使用した例が非常に少ないため、どの程度適用できるかはわかりません。
4

2 に答える 2

3

atomic<>プリミティブ型に限定されません。自明にコピー可能なatomic<>Tでの使用が許可されています。c++11 標準のセクション29.5 Atomic typesから ( にも記載されています):std::atomic

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

アトミック アクセスが必要atomic<>なオブジェクトを使用できない場合は、元のオブジェクトとstd::mutex. これは、lock_guard<>が新しいスレッド セーフ オブジェクトの getter および setter 内でのみ使用され、コード全体に散らばっていないことを意味します。Atemplateは、必要なスレッド セーフ機構を定義できる場合があります。

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();
于 2013-05-24T19:26:41.550 に答える
1

アトミックは、自明にコピー可能なクラス (つまり、カスタム コピー コンストラクターを持たず、メンバーも自明にコピー可能なクラス) に限定されます。

この要件には、アトミックにとって大きな利点があります。

  • コンストラクターがスローしたため、アトミック操作をスローできません
  • すべてのアトミックは、データをコピーするためのロック (スピンロックまたはミューテックス) と memcpy でモデル化できます。
  • すべてのアトミックには有限の実行時間 (有界) があります。

アトミックはスピンロックを使用して実装されることがあり、スピンロックを保持している間は無制限のタスクを回避することが強く望まれるため、後者は特に便利です。コンストラクターが許可されている場合、実装は完全なミューテックスにフォールバックする必要がある傾向があります。これは、非常に小さなクリティカル セクションのスピンロックよりも低速です。

于 2013-09-03T06:13:58.203 に答える