我可以拥有一个增强无锁的lambdas队列吗?

时间:2014-01-28 12:42:09

标签: c++ multithreading boost c++11 lambda

我正在尝试实现跨多个线程的消息传递系统。 boost::lockfree::queue似乎是一个很好的方向,不幸的是我无法创建std::functionboost::function类型的队列,因为显然他们没有简单的任务和析构函数,这是要求boost::lockfree::queue

我的以下代码:

#include <cassert>
//#include <functional>
#include <iostream>

#include <boost/function.hpp>
#include <boost/lockfree/queue.hpp>

int main()
{
  boost::lockfree::queue<boost::function<void(int)>> queue;
  assert(queue.is_lock_free());

  for(int j = 0; j < 50; ++j) {
    queue.push([] (int i) { std::cout << i << std::endl; });
  }

  int i = 0;
  boost::function<void(int)> functor;
  while (queue.pop(functor)) {
    functor(i++);
  }
}

产生以下输出:

In file included from /usr/include/boost/integer.hpp:23:0,
                 from /usr/include/boost/function/function_base.hpp:21,
                 from /usr/include/boost/function/detail/prologue.hpp:17,
                 from /usr/include/boost/function.hpp:24,
                 from lockfree.cpp:5:
/usr/include/boost/lockfree/queue.hpp: In instantiation of ‘class boost::lockfree::queue<boost::function<void(int)> >’:
lockfree.cpp:10:54:   required from here
/usr/include/boost/lockfree/queue.hpp:81:5: error: static assertion failed (boost::has_trivial_destructor<T>::value)
     BOOST_STATIC_ASSERT((boost::has_trivial_destructor<T>::value));
     ^
/usr/include/boost/lockfree/queue.hpp:85:5: error: static assertion failed (boost::has_trivial_assign<T>::value)
     BOOST_STATIC_ASSERT((boost::has_trivial_assign<T>::value));

有没有办法让这项工作?

3 个答案:

答案 0 :(得分:5)

如果这是一个选项,您仍然可以将无状态 lambdas与原始函数指针一起使用:

#include <cassert>
#include <functional>
#include <iostream>

#include <boost/function.hpp>
#include <boost/lockfree/queue.hpp>

int main() {
    //boost::lockfree::queue<boost::function<void(int)>> queue(50);
    boost::lockfree::queue<void (*)(int)> queue(50);
    assert(queue.is_lock_free());

    for (int j = 0; j < 50; ++j) {
        queue.push([](int i) { std::cout << i << std::endl; });
    }

    int i = 0;
    boost::function<void(int)> functor;
    while (queue.pop(functor)) {
        functor(i++);
    }
}

http://coliru.stacked-crooked.com/a/d57770e3be029760

答案 1 :(得分:3)

您可以使用指针来模拟普通类型。 (这适用于所有lambdas)

#include <cassert>
#include <functional>
#include <iostream>

#include <boost/function.hpp>
#include <boost/lockfree/queue.hpp>

int main()
{
  boost::lockfree::queue<boost::function<void(int)>*> queue(3);
  assert(queue.is_lock_free());

  for(int j = 0; j < 50; ++j) {
    auto function = [] (int i) { std::cout << i << std::endl; };
    queue.push(new boost::function<void(int)>(function));
  }

  int i = 0;
  boost::function<void(int)> * functor;
  while (queue.pop(functor)) {
    functor->operator()(i++);
    delete functor;
  }
}

答案 2 :(得分:1)

boost :: function不满足无锁队列的要求:

  
      
  • 琐碎的复制构造函数
  •   
  • 琐碎的作业
  •   
  • 琐碎的析构者
  •   

邮件列表中的thread描述了您遇到的同样问题,解决方案可能是使用可以复制的仿函数对象。