zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    linux中的cd ..和cd -命令有什么区别?
    GCC使用
  • 原文地址:https://www.cnblogs.com/zhongpan/p/7526903.html
Copyright © 2011-2022 走看看