boost::lockfree使用介紹


boost::lockfree是boost1.53引入的無鎖數據結構,包括boost::lockfree::stack、boost::lockfree::queue和boost::lockfree::spsc_queue三種,前兩種用於多生產者/多消費者場景,第三個用於單生產者/單消費者場景,下面對它們的使用進行詳細介紹,以boost::lockfree::stack為例,其他類似。

構造

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_表示非線程安全;

  • 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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM