boost::lockfree是boost1.53引入的無鎖數據結構,包括boost::lockfree::stack、boost::lockfree::queue和boost::lockfree::spsc_queue三種,前兩種用於多生產者/多消費者場景,第三個用於單生產者/單消費者場景,下面對它們的使用進行詳細介紹,以boost::lockfree::stack爲例,其餘相似。node
boost::lockfree::stack源代碼以下(boost 1.65):數組
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES template <typename T, class A0, class A1, class A2> #else template <typename T, typename ...Options> #endif class stack { private: #ifndef BOOST_DOXYGEN_INVOKED BOOST_STATIC_ASSERT(boost::is_copy_constructible<T>::value); #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES typedef typename detail::stack_signature::bind<A0, A1, A2>::type bound_args; #else typedef typename detail::stack_signature::bind<Options...>::type bound_args; #endif static const bool has_capacity = detail::extract_capacity<bound_args>::has_capacity; static const size_t capacity = detail::extract_capacity<bound_args>::capacity; static const bool fixed_sized = detail::extract_fixed_sized<bound_args>::value; static const bool node_based = !(has_capacity || fixed_sized); static const bool compile_time_sized = has_capacity; /* 省略 */ public: typedef T value_type; typedef typename implementation_defined::allocator allocator; typedef typename implementation_defined::size_type size_type; //! Construct stack // @{ stack(void): pool(node_allocator(), capacity) { BOOST_ASSERT(has_capacity); initialize(); } template <typename U> explicit stack(typename node_allocator::template rebind<U>::other const & alloc): pool(alloc, capacity) { BOOST_STATIC_ASSERT(has_capacity); initialize(); } explicit stack(allocator const & alloc): pool(alloc, capacity) { BOOST_ASSERT(has_capacity); initialize(); } // @} //! Construct stack, allocate n nodes for the freelist. // @{ explicit stack(size_type n): pool(node_allocator(), n) { BOOST_ASSERT(!has_capacity); initialize(); } template <typename U> stack(size_type n, typename node_allocator::template rebind<U>::other const & alloc): pool(alloc, n) { BOOST_STATIC_ASSERT(!has_capacity); initialize(); }
boost::lockfree::stack的第一個模板參數是元素類型,後面3個參數是用來配置stack的,沒有順序要求:安全
boost::lockfree::fixed_sized<false>
,若是爲true,則內部使用數組保存元素,大小不能動態增加;boost::lockfree::fixed_sized<true>
,和運行時指定大小是互斥的,見下面的例子;boost::lockfree::allocator<std::allocator<void>>
。例如:數據結構
//表示動態大小,初始大小爲4,用完了再動態增加;此時必須在構造函數指定初始大小,不然斷言失敗; boost::lockfree::stack<int> s(4); //表示大小固定,運行時指定初始大小爲4,用完後再push就會失敗;此時必須在構造函數指定初始大小,不然斷言失敗; boost::lockfree::stack<int, boost::lockfree::fixed_sized<true>> s1(4); //表示大小固定,編譯時指定初始大小爲4,用完後再push就會失敗;此時不能在構造函數指定初始大小,不然斷言失敗; boost::lockfree::stack<int, boost::lockfree::capacity<4>> s2; //和上面同樣,設置了capacity,fixed_size就老是true boost::lockfree::stack<int, boost::lockfree::fixed_size<false>, boost::lockfree::capacity<4>> s3;
bool push(T const & v) bool bounded_push(T const & v) template <typename ConstIterator> ConstIterator push(ConstIterator begin, ConstIterator end) template <typename ConstIterator> ConstIterator bounded_push(ConstIterator begin, ConstIterator end) bool unsynchronized_push(T const & v) ConstIterator unsynchronized_push(ConstIterator begin, ConstIterator end)
bounded_表示不動態增加,當初始大小用完後再push就會失敗;
unsynchronized_表示非線程安全;函數
bool pop(T & ret) template <typename U> bool pop(U & ret) bool unsynchronized_pop(T & ret) template <typename U> bool unsynchronized_pop(U & ret)
unsynchronized_表示非線程安全;atom
template <typename Functor> bool consume_one(Functor & f) template <typename Functor> bool consume_one(Functor const & f) template <typename Functor> size_t consume_all(Functor & f) template <typename Functor> size_t consume_all(Functor const & f) template <typename Functor> size_t consume_all_atomic(Functor & f) template <typename Functor> size_t consume_all_atomic(Functor const & f) template <typename Functor> size_t consume_all_atomic_reversed(Functor & f) template <typename Functor> size_t consume_all_atomic_reversed(Functor const & f)
_one表示只消費1個元素;
_all表示消費全部元素;
_atomic表示消費過程是原子的,其間其餘操做對其是不可見的。
_reversed表示倒序消費。線程
//預分配空閒節點數,和編譯時設置capacity互斥;線程安全,可能阻塞 void reserve(size_type n) //非線程安全 void reserve_unsafe(size_type n) //判斷是否爲空 bool empty(void) const
#include <boost/lockfree/stack.hpp> int main(int argc, char *argv[]) { boost::lockfree::stack<int> s(64); //producer for (int i = 0; i < 1000; i++) { s.push(i); } //consumer s.consume_all([](int i) { std::cout << i << std::endl; }); return 0; }