C ++ 11只能将原始数据类型声明为原子吗?

我想知道,只能将原始数据类型在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;
}

但是,如果这些setter和getter方法在不同的线程中调用,我认为这可能会导致未定义的行为。 如果我能够像下面这样声明foo就好了:

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

......所有对foo的操作都将以原子的方式进行。 在我的项目的应用程序中,可能会有数百个这样的foo变量在数十个类中声明,并且我觉得使对象更改和访问“原子”可以说更加方便,而不必声明和锁定_guard各地的互斥体。

这是不可能的,还是有更好的方法,还是我真的必须在任何地方都使用互斥锁和lock_guard?

更新

  • 任何接受者? 我一直在网上钓鱼以获得体面的信息,但是使用原子的例子很少,我不能确定它可以应用的程度。

  • atomic<>不限于原始类型。 允许使用atomic<>T类型,这是可以复制的。 来自第29.5节c ++ 11标准的原子类型(它也在std::atomic ):

    有一个通用的类模板原子。 模板参数T的类型应是可复制的(3.9)。

    如果需要原子访问的对象不能与atomic<>一起使用,则定义包含原始对象和std::mutex新对象。 这意味着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();
    

    原子学仅限于可复制的类(即没有自定义拷贝构造函数的类,其成员也可以复制)。

    这个要求对原子有很大的好处:

  • 由于构造函数抛出,没有原子操作可以抛出
  • 所有原子都可以用锁(spinlock或mutex)和memcpy来模拟复制数据。
  • 所有原子都具有有限的运行时间(有界)。
  • 后者是特别有用的,因为原子有时使用自旋锁来实现,并且非常希望在保持自旋锁的同时避免无限的任务。 如果允许任何构造函数,那么实现往往需要回退到完整的互斥锁,这对于非常小的关键部分来说比自旋锁要慢。

    链接地址: http://www.djcxy.com/p/13705.html

    上一篇: C++11 Can only primitive data types be declared atomic?

    下一篇: Sun as a light source using opengl and c++