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;
    }
    
  • 相关阅读:
    Ubuntu上64位adv无法创建问题
    Java 数据结构与算法分析学习
    博客第一天——新的梦幻之旅
    android开发第一天
    Ubuntu下OpenGL开发环境的搭建
    [ZZ]WindowsForm应用程序调用WebService
    WindowsForm应用程序调用WebService
    Hello World
    Apache Ant编写build.xml的自动提示 ANT DTD
    Serial Interface之I2C:关于DS1624 2线通信SDA保持时间的说明
  • 原文地址:https://www.cnblogs.com/zhongpan/p/7526903.html
Copyright © 2011-2022 走看看