boost::lockfree使用介紹

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:是否固定大小,默認爲boost::lockfree::fixed_sized<false>,若是爲true,則內部使用數組保存元素,大小不能動態增加;
  • boost::lockfree::capacity:編譯時設置內部數組大小,設置了capacity意味着必定是boost::lockfree::fixed_sized<true>,和運行時指定大小是互斥的,見下面的例子;
  • boost::lockfree::allocator:設置分配器,默認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;

成員方法

  • push:壓入一個元素到容器,除了unsynchronized_,都是線程安全的。全部都是非阻塞的。
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_表示非線程安全;函數

  • pop:從容器中彈出一個元素,除了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

  • consume_:從容器彈出1個或所有元素,並應用某個函數對象。線程安全或阻塞與否取決於函數對象。
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;
}
相關文章
相關標籤/搜索