C ++原子列表容器

时间:2015-06-16 08:59:07

标签: c++ list stl containers atomic

我正在玩std::atomic<std::list<int> > atomicList; ,但我认为我并不完全理解这个概念。我想知道为什么没有原子容器。所以我玩了一下。首先,我尝试了以下内容:

noexcept

但正如其他人已经指出的那样,这不起作用,因为构造函数是template<class T> class MyList { public: //Make sure that no exception is thrown MyList() noexcept try: l() {}catch(...) {} void push_back(const T &t) { l.push_back(t); } void pop_front() { l.pop_front(); } size_t size() const { return l.size(); } private: list<T> l; }; atomic<MyList<int> > atomicList; 。所以我创造了某种黑客攻击:

#include <list>
#include <thread>
#include <sys/time.h>
#include <iostream>
#include <atomic>

using namespace std;

template<class T>
class MyList
{

public:
    MyList() noexcept
        try: l()
    {}catch(...) {}

    void push_back(const T &t) { l.push_back(t); }

    void pop_front() { l.pop_front(); }

    size_t size() const { return l.size(); }

private:
    list<T> l;

};

atomic<MyList<int> > l;

void work()
{
    for(unsigned int i = 0; i < 100000; ++i)
    {
        //Called operator()
        ((MyList<int>&)l).push_back(i);
        ((MyList<int>&)l).push_back(((MyList<int>&)l).size());
        ((MyList<int>&)l).pop_front();
    }
}

int main(int argc, char *args[])
{
    struct timeval time1;
    struct timeval time2;
    gettimeofday(&time1, 0);
    thread t1(work);
    thread t2(work);
    thread t3(work);
    thread t4(work);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    gettimeofday(&time2, 0);
    cout<<((time2.tv_sec-time1.tv_sec)+double(time2.tv_usec-time1.tv_usec)/1000000)<<endl;
}

现在我使用它,但我发现它没有正常工作,我得到了分段错误。

有人可以解释为什么不可能以这种方式创建原子列表吗?

编辑:如果有人想看看我的测试程序如何真正寻求更好的理解:

{!! Form::open(['route' => 'contributions.finalise', 'method' => 'POST']) !!}
    // Add CSRF Field
    {!! csrf_field() !!}

    {!! Form::input('hidden','amount', null, ['id' => "contribute-amount"]) !!}

    <button type="submit">Submit</button>
{!! Form::close() !!}

2 个答案:

答案 0 :(得分:4)

第一个也是最重要的问题:这可能无法奏效。您需要围绕成员函数的执行进行同步,而不是检索列表。 std::atomic甚至没有开始像你需要的那样。

关于您的尝试实施,将atomic<T>投射到T&无法做任何合理的事情。

即使它是有意义的,这样的演员会完全忘记你的对象的原子性,所以你对引用所做的任何事情都不会成为原子操作。

答案 1 :(得分:1)

((MyList<int>&)l).push_back(i);

std::atomic未向引用提供转换运算符。如果你使用static_cast,它甚至不会编译,但是这里的C-cast直接将std::atomic<MyList<int>>重新解释为MyList<int>,这有充分的理由不能工作。

您无法直接修改std::atomic中的内容。您需要使用load()检索数据副本,修改此副本,然后将其与store()交换回来。