zoukankan      html  css  js  c++  java
  • object pool

    这是一个简单易用的对象池,很多系统对资源的访问快捷性及可预测性有严格要求,列入包括网络连接、对象实例、线程和内存。而且还要求解决方案可扩展,能应付存在大量资源的情形。

    object pool针对特定类型的对象循环利用,这些对象要么创建开销巨大,要么可创建的数量有限。而且在pool中的对象需要做到无状态。

    如何使用

    utility::object_pool_t<int> pool1([]()
    {
    return std::make_shared<int>(10);
    });

    {
    auto t = pool1.get();
    }

    指定类型,创建一个pool对象,同时提供创建对象函数。

    获取接口get,返回一个std::shared_ptr<T>对象,在该对象析构时自动返回到pool中,不需要额外的释放接口

    实现

    #ifndef __UTILITY_OBJECT_POOL_HPP
    #define __UTILITY_OBJECT_POOL_HPP


    #include <memory>
    #include <list>
    #include <functional>
    #include <cstdint>


    namespace utility {

    template < typename T >
    struct object_pool_traits_t;


    template < typename T, typename AllocatorT >
    struct object_pool_traits_t<std::list<std::shared_ptr<T>, AllocatorT>>
    {
    typedef std::shared_ptr<T> value_t;

    static value_t pop(std::list<value_t, AllocatorT> &l)
    {
    if( l.empty() )
    {
    return value_t();
    }
    else
    {
    value_t val = l.front();
    l.pop_front();
    return val;
    }
    }


    static void push(std::list<value_t, AllocatorT> &l, value_t && val)
    {
    l.push_back(std::move(val));
    }


    template < typename HandlerT >
    static void for_each(std::list<value_t, AllocatorT> &l, const HandlerT &handler)
    {
    std::for_each(l.cbegin(), l.cend(), handler);
    }


    static std::uint32_t size()
    {
    return l.size();
    }
    };



    template <
    typename T,
    typename C = std::list<std::shared_ptr<T>>
    >
    struct object_pool_t
    {
    typedef std::shared_ptr<T> value_t;
    typedef C queue_t;
    typedef std::shared_ptr<queue_t> pool_t;

    typedef std::function<value_t()> create_handler_t;
    static_assert(std::is_same<value_t, typename queue_t::value_type>::value, "container value_type must be std::shared_ptr<T> type");

    create_handler_t create_handler_;
    pool_t pool_;


    object_pool_t(const create_handler_t &create_handler)
    : pool_(std::make_shared<queue_t>())
    , create_handler_(create_handler)
    {
    if( create_handler_ == nullptr )
    create_handler_ = []()->value_t{ return std::make_shared<value_t::element_type>(); };
    }


    template < typename AllocatorT = std::allocator<char> >
    value_t get(const AllocatorT &allocator = AllocatorT())
    {
    value_t obj = object_pool_traits_t<queue_t>::pop(*pool_);
    if( !obj )
    obj = create_handler_();

    return std::shared_ptr<T>(obj.get(),
    [=](T *) mutable
    {
    object_pool_traits_t<queue_t>::push(*pool_, std::move(obj));
    }, allocator);
    }


    value_t raw_aciquire()
    {
    value_t obj = object_pool_traits_t<queue_t>::pop(*pool_);
    if( !obj )
    obj = create_handler_();

    return obj;
    }


    void raw_release(value_t &&val)
    {
    object_pool_traits_t<queue_t>::push(*pool_, std::move(val));
    }


    void for_each(const std::function<void(const value_t &)> &handler)
    {
    object_pool_traits_t<queue_t>::for_each(*pool_, handler);
    }


    std::uint32_t size() const
    {
    return object_pool_traits_t<queue_t>::size(*pool_);
    }
    };
    }

    #endif

    如何扩展

    1. 先扩展pool容器

    namespace utility  {

    template < >
    struct object_pool_traits_t<tbb::concurrent_bounded_queue<std::shared_ptr<int>>>
    {
    typedef std::shared_ptr<int> value_t;
    typedef tbb::concurrent_bounded_queue<value_t> container_t;


    static value_t pop(container_t &l)
    {
    value_t v;
    if( !l.try_pop(v) )
    return std::make_shared<int>();

    return v;
    }

    static void push(container_t &l, value_t && val)
    {
    l.push(val);
    }
    };

    }
    2. 定义类
    utility::object_pool_t<int, tbb::concurrent_bounded_queue<std::shared_ptr<int>>> pool2([]()
    {
    return std::make_shared<int>(1);
    });
    3. 获取资源
    {
    auto t = pool2.get(tbb::tbb_allocator<char>());
    }

    {
    auto n = pool2.raw_aciquire();
    *n = 12;
    pool2.raw_release(std::move(n));
    }


    over
  • 相关阅读:
    如何解决selenium打开chrome提示chromedriver.exe已停止工作
    移动端弱网测试 fiddle
    android 真机设备识别不出adb interface
    网络基础知识
    《Mongo权威指南》学习手记
    MongoDB数据库备份
    windows下安装mongoDB(zip版)
    ubuntu apt
    docker 免sudo设置(仅3个命令)
    ubuntu18.04双卡机安装ubidia驱动遇到的坑
  • 原文地址:https://www.cnblogs.com/yu-yu/p/3329679.html
Copyright © 2011-2022 走看看