Object Pool 对象池的C++11使用(转)

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

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

然后转了这位博主的代码,还在研究中

const int MaxObjectNum = 10;
template <typename T>
class ObjectPool
{
    template <typename... Args>
    using Constructor = std::function<std::shared_ptr<T>(Args...)>;

public:
    ObjectPool(void)
        : m_bNeedClear(false)
    {
    }

    virtual ~ObjectPool(void)
    {
        m_bNeedClear = true;
    }

    template <typename... Args>
    void Init(size_t num, Args &&... args)
    {
        if (num <= 0 || num > MaxObjectNum)
        {
            throw std::logic_error("object num out of range.");
        }

        auto constructName = typeid(Constructor<Args...>).name();

        for (size_t i = 0; i < num; i++)
        {
            m_object_map.emplace(constructName,
                                 std::shared_ptr<T>(new T(std::forward<Args>(args)...), [constructName, this](T *t) {
                                     if (m_bNeedClear)
                                     {
                                         delete t;
                                     }
                                     else
                                     {
                                         m_object_map.emplace(constructName, std::shared_ptr<T>(t));
                                     }
                                 }));
        }
    }

    template <typename... Args>
    std::shared_ptr<T> Get()
    {
        string constructName = typeid(Constructor<Args...>).name();

        auto range = m_object_map.equal_range(constructName);

        for (auto it = range.first; it != range.second; ++it)
        {
            auto ptr = it->second;
            m_object_map.erase(it);
            return ptr;
        }

        return nullptr;
    }

private:
    std::multimap<std::string, std::shared_ptr<T>> m_object_map;
    bool m_bNeedClear;
};

ObjectPool.cpp

class BigObject
{
public:
    BigObject() {}

    BigObject(int a) {}

    BigObject(const int &a, const int &b)
    {
    }

    void Print(const string &str)
    {
        cout << str << endl;
    }
};

void Print(shared_ptr<BigObject> p, const string &str)
{
    if (p != nullptr)
    {
        p->Print(str);
    }
}

int main()
{
    ObjectPool<BigObject> pool;
    pool.Init(2);
    {
        auto p = pool.Get();
        Print(p, "p");

        auto p2 = pool.Get();
        Print(p2, "p2");
    }

    auto p = pool.Get();
    Print(p, "p");

    auto p2 = pool.Get();
    Print(p2, "p2");

    auto p3 = pool.Get();
    Print(p3, "p3");

    pool.Init(2, 1);

    auto p4 = pool.Get<int>();

    Print(p4, "p4");
    getchar();
    return 0;
}

test.cpp

还有个半同步半异步的线程池,这个我看懂的多一点,就是用队列和信号量去实现多线程并发

#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>
#include <functional>
#include <memory>
#include <atomic>
using namespace std;

namespace itstation
{
template <typename T>
class SynaQueue
{
public:
    SynaQueue(int maxSize)
        : m_maxSize(maxSize), m_needStop(false)
    {
    }

    void Put(const T &x)
    {
        Add(x);
    }
    void Put(T &&x)
    {
        Add(forward<T>(x)); //完美转发,不改变参数的类型
    }
    void Take(list<T> &list)
    {
        std::unique_lock<mutex> locker(m_mutex);
        // 判断式, 当都不满足条件时,条件变量会释放mutex, 并将线程置于waiting状态, 等待其他线程调用notify_one/all 将其唤醒。
        // 当满足其中一个条件时继续执行, 将队列中的任务取出,唤醒等待添加任务的线程
        // 当处于waiting状态的线程被唤醒时,先获取mutex,检查条件是否满足,满足-继续执行,否则释放mutex继续等待
        m_notEmpty.wait(locker, [this] { return m_needStop || NotEmpty(); });
        if (m_needStop)
            return;
        list = move(m_queue);
        m_notFull.notify_one();
    }
    void Take(T &t)
    {
        unique_lock<mutex> locker(m_mutex); // 锁
        m_notEmpty.wait(locker, [this] { return m_needStop || NotEmpty(); });
        if (m_needStop)
            return;
        t = m_queue.front();
        m_queue.pop_front();
        m_notFull.notify_one();
    }
    void Stop()
    {
        {
            lock_guard<mutex> locker(m_mutex);
            m_needStop = true;
        }
        m_notFull.notify_all(); // 将所有等待的线程全部唤醒,被唤醒的进程检查m_needStop,为真,所有的线程退出执行
        m_notEmpty.notify_all();
    }

private:
    bool NotFull() const
    {
        bool full = m_queue.size() >= m_maxSize;
        if (full)
            cout << "缓冲区满了,需要等待。。。。" << endl;
        return !full;
    }
    bool NotEmpty() const
    {
        bool empty = m_queue.empty();
        if (empty)
            cout << "缓冲区空了,需要等待,。。。异步层线程: " << this_thread::get_id() << endl;
        return !empty;
    }

    template <typename F>
    void Add(F &&x)
    {
        unique_lock<mutex> locker(m_mutex);                                 // 通过m_mutex获得写锁
        m_notFull.wait(locker, [this] { return m_needStop || NotFull(); }); // 没有停止且满了,就释放m_mutex并waiting;有一个为真就继续执行
        if (m_needStop)
            return;
        m_queue.push_back(forward<F>(x));
        m_notEmpty.notify_one();
    }

private:
    list<T> m_queue;               //缓冲区
    mutex m_mutex;                 // 互斥量
    condition_variable m_notEmpty; // 条件变量
    condition_variable m_notFull;
    int m_maxSize;   //同步队列最大的size
    bool m_needStop; // 停止标识
};

const int MaxTaskCount = 100;
class ThreadPool
{
public:
    using Task = function<void()>;
    ThreadPool(int numThread = thread::hardware_concurrency())
        : m_queue(MaxTaskCount)
    {
        Start(numThread);
    }

    virtual ~ThreadPool()
    {
        Stop();
    }

    void Stop()
    {
        call_once(m_flag, [this] { StopThreadGroup(); });
    }

    void AddTask(Task &&task)
    {
        m_queue.Put(forward<Task>(task));
    }

    void AddTask(const Task &task)
    {
        m_queue.Put(task);
    }

private:
    void Start(int numThreads)
    {
        m_running = true;
        //创建线程组
        for (int i = 0; i < numThreads; i++)
        {
            m_threadgroup.emplace_back(make_shared<thread>(&ThreadPool::RunInThread, this));
        }
    }

    // 每个线程都执行这个函数
    void RunInThread()
    {
        while (m_running)
        {
            //取任务分别执行
            list<Task> list;
            m_queue.Take(list);
            for (auto &task : list)
            {
                if (!m_running)
                    return;

                task();
            }
        }
    }
    void StopThreadGroup()
    {
        m_queue.Stop();    // 同步队列中的线程停止
        m_running = false; // 让内部线程跳出循环并推出
        for (auto thread : m_threadgroup)
        {
            if (thread)
                thread->join();
        }
        m_threadgroup.clear();
    }

private:
    list<shared_ptr<thread>> m_threadgroup; // 处理任务的线程组, 链表中存储着指向线程的共享指针
    SynaQueue<Task> m_queue;                //同步队列
    atomic_bool m_running;                  // 是否停止的标识
    once_flag m_flag;
};
} // namespace itstation

ObjectPool.h

#include <stdio.h>
#include <iostream>
#include "ObjectPool.h"
#include <list>
using namespace std;
using namespace itstation;

void TestThreadPool()
{
    ThreadPool pool(2);
    thread thd1([&pool] {
        for (int i = 0; i < 10; i++)
        {
            auto thrID = this_thread::get_id();
            pool.AddTask([thrID, i] {cout << "同步层线程1的线程ID:" << thrID << "  这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds(2)); });
        }
    });

    thread thd2([&pool] {
        for (int i = 0; i < 10; i++)
        {
            auto thrID = this_thread::get_id();
            pool.AddTask([thrID, i] {cout << "同步层线程2的线程ID:" << thrID << "  这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds(2)); });
        }
    });

    this_thread::sleep_for(chrono::seconds(45));
    pool.Stop();
    thd1.join();
    thd2.join();
}
int main()
{
    TestThreadPool();

    getchar();
    return 0;
}

test.cpp

原文地址:https://www.cnblogs.com/BobHuang/p/11259471.html

时间: 2024-11-10 15:22:53

Object Pool 对象池的C++11使用(转)的相关文章

Object Pooling(对象池)实现

在文章开始之前首先要思考的问题是为什么要建立对象池.这和.NET垃圾回收机制有关,正如下面引用所说,内存不是无限的,垃圾回收器最终要回收对象,释放内存.尽管.NET为垃圾回收已经进行了大量优化,例如将托管堆划分为 3 Generations(代)并设定新建的对象回收的最快,新建的短生命周期对象将进入 Gen 0(新建对象大于或等于 85,000 字节将被看作大对象,直接进入 Gen 2),而 Gen 0 通常情况下分配比较小的内存,因此Gen 0 将回收的非常快.而高频率进行垃圾回收导致 CPU

[译]Unity3D内存管理——对象池(Object Pool)

从一个简单的对象池类开始说起 对象池背后的理念其实是非常简单的.我们将对象存储在一个池子中,当需要时在再次使用,而不是每次都实例化一个新的对象.池的最重要的特性,也就是对象池设计模式的本质是允许我们获取一个“新的”对象而不管它真的是一个新的对象还是循环使用的对象.该模式可以用以下简单的几行代码实现: public class ObjectPool<T> where T : class, new() { private Stack<T> m_objectStack = new Sta

Unity内存管理之对象池(Object Pool)

第一篇博客,打算和大家分享一下关于Unity开发当中用到的对象池,那么何为对象池呢? [对象池]:对象池是一种经常用到的内存管理服务,它的作用在于可以减少从头创建每个对象的系统开销. 众所周知,在Unity游戏开发的过程中经常会创建一些新的对象,如果数量较少还可以接受,如果创建的新对象数量庞大,那么对内存而言是一个极大的隐患.例如射击游戏当中,每发射一颗子弹,都要创建一个新的子弹对象,那么子弹是数量庞大,可想而知一场游戏当中会创建多少这样的新对象,那么如果这些子弹创建之后都对游戏起着关键且持续性

go语言学习--go的临时对象池--sync.Pool

一个sync.Pool对象就是一组临时对象的集合.Pool是协程安全的. Pool用于存储那些被分配了但是没有被使用,而未来可能会使用的值,以减小垃圾回收的压力.一个比较好的例子是fmt包,fmt包总是需要使用一些[]byte之类的对象,golang建立了一个临时对象池,存放着这些对象,如果需要使用一个[]byte,就去Pool里面拿,如果拿不到就分配一份. 这比起不停生成新的[]byte,用完了再等待gc回收来要高效得多. type buffer []byte // pp是用于存储printe

Go36-33-临时对象池(sync.Pool)

临时对象池(sync.Pool) sync.Pool是Go语言标准库中的一个同步工具. 介绍 sync.Pool类型可以被称为临时对象池,它的值可以被用来存储临时的对象.它属于结构体类型,在它的值被真正使用之后,就应该再被复制了. 临时对象,就是不需要持久使用的某一类值.这类值对于程序来说可有可无,但如果有的话明显更好.它们的创建和销毁可以在任何时候发生,并且完全不会影响到程序功能.同时,它们也应该是无需被区分的,其中的任何一个值都可以代替另一个.如果某类值完全符合上述条件,就可以把它们存储到临

对象池实现分析

对象池实现分析 什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池化技术最终要的就是重复的使用池内已经创建的对象.从上面的内容就可以看出对象池适用于以下几个场景: 创建对象的开销大 会创建大量的实例 限制一些资源的使用 如果创建一个对象的开销特别大,那么提前创建一些可以使用的并且缓存起来(池化技术就是重复使用对象,提前创建并缓存起来重复使用就是池化

深度剖析C++对象池自动回收技术实现

http://www.tuicool.com/articles/mQBfQfN 对象池可以显著提高性能,如果一个对象的创建非常耗时或非常昂贵,频繁去创建的话会非常低效.对象池通过对象复用的方式来避免重复创建对象,它会事先创建一定数量的对象放到池中,当用户需要创建对象的时候,直接从对象池中获取即可,用完对象之后再放回到对象池中,以便复用.这种方式避免了重复创建耗时或耗资源的大对象,大幅提高了程序性能.本文将探讨对象池的技术特性以及源码实现. 对象池类图 ObjectPool:管理对象实例的pool

Netty轻量级对象池实现分析

什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池化技术最终要的就是重复的使用池内已经创建的对象.从上面的内容就可以看出对象池适用于以下几个场景: 创建对象的开销大 会创建大量的实例 限制一些资源的使用 如果创建一个对象的开销特别大,那么提前创建一些可以使用的并且缓存起来(池化技术就是重复使用对象,提前创建并缓存起来重复使用就是池化)可以降低创建对

享元模式(对象池模式)

我在网上也看到了一些实现,感觉都不是太满意,所以按照我的理解写了一份 1 <?php 2 3 /** 4 * 具体的需要缓存的对象, 因new的代价太高昂, 所以做一个缓存 5 */ 6 class Worker 7 { 8 public function __construct() 9 { 10 //做一些代价高昂的事情,比如创建线程 11 } 12 13 public function run($class, $functionName) 14 { 15 //对$class做一些事情 16