Object Pool 对象池的C++11使用(转)
很多系统对资源的访问快捷性及可预测性有严格要求,列入包括网络连接、对象实例、线程和内存。而且还要求解决方案可扩展,能应付存在大量资源的情形。
object pool针对特定类型的对象循环利用,这些对象要么创建开销巨大,要么可创建的数量有限。而且在pool中的对象需要做到无状态。
然后转了这位博主的代码,还在研究中
const int MaxObjectNum = ;
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 <= || num > MaxObjectNum)
{
throw std::logic_error("object num out of range.");
} auto constructName = typeid(Constructor<Args...>).name(); for (size_t i = ; 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();
{
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(, ); auto p4 = pool.Get<int>(); Print(p4, "p4");
getchar();
return ;
}
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 = ;
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 = ; 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();
thread thd1([&pool] {
for (int i = ; i < ; i++)
{
auto thrID = this_thread::get_id();
pool.AddTask([thrID, i] {cout << "同步层线程1的线程ID:" << thrID << " 这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds()); });
}
}); thread thd2([&pool] {
for (int i = ; i < ; i++)
{
auto thrID = this_thread::get_id();
pool.AddTask([thrID, i] {cout << "同步层线程2的线程ID:" << thrID << " 这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds()); });
}
}); this_thread::sleep_for(chrono::seconds());
pool.Stop();
thd1.join();
thd2.join();
}
int main()
{
TestThreadPool(); getchar();
return ;
}
test.cpp
Object Pool 对象池的C++11使用(转)的更多相关文章
- JedisCluster中应用的Apache Commons Pool对象池技术
对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分. apache common pool 官方文档可以参考:https://c ...
- Object Pooling(对象池)实现
在文章开始之前首先要思考的问题是为什么要建立对象池.这和.NET垃圾回收机制有关,正如下面引用所说,内存不是无限的,垃圾回收器最终要回收对象,释放内存.尽管.NET为垃圾回收已经进行了大量优化,例如将 ...
- .NET Core中Object Pool的简单使用
前言 复用,是一个重要的话题,也是我们日常开发中经常遇到的,不可避免的问题. 举个最为简单,大家最为熟悉的例子,数据库连接池,就是复用数据库连接. 那么复用的意义在那里呢? 简单来说就是减少不必要的资 ...
- 缓冲&缓存&对象池概念的理解
一).缓冲 作用:缓解程序上下层之间的性能差异. 1).当上层组件的性能优于下层组件时加入缓冲机制可以减少上层组件对下 层组件的等待时间. 2).上层组件不需要等待下层组件接收全部数据,即可返回操作, ...
- java对象池化技术
https://blog.csdn.net/tiane5hao/article/details/85957840 文章目录 先写一个简单通用的对象池 通过上面的通用池实现jedis连接池 连接池测试 ...
- Java堆外内存之一:堆外内存场景介绍(对象池VS堆外内存)
最近经常有人问我在Java中使用堆外(off heap)内存的好处与用途何在.我想其他面临几样选择的人应该也会对这个答案感兴趣吧. 堆外内存其实并无特别之处.线程栈,应用程序代码,NIO缓存用的都是堆 ...
- Unity实现简单的对象池
一.简介 先说说为什么要使用对象池 在Unity游戏运行时,经常需要生成一些物体,例如子弹.敌人等.虽然Unity中有Instantiate()方法可以使用,但是在某些情况下并不高效.特别是对于那些需 ...
- 设计模式之美:Object Pool(对象池)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):实现 DatabaseConnectionPool 类. 实现方式(二):使用对象构造方法和预分配方式实现 ObjectPool ...
- [译]Unity3D内存管理——对象池(Object Pool)
原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...
随机推荐
- svn插件的所有链接
http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240
- filterBuilders 构建过滤器query
FilterBuilders构建过滤器Query package com.elasticsearch; import org.elasticsearch.action.ActionListener; ...
- python随机生成图片
#-*-coding:utf-8-*- import tensorflow as tf import numpy as np import cv2 image = tf.random_uniform( ...
- Linux常用命令的缩写含义
命令缩写: ls:list(列出目录内容) cd:Change Directory(改变目录) su:switch user 切换用户rpm:redhat package manager 红帽子打包管 ...
- 【python之路46】内置函数2,是【python之路18】的补充
将3.5版本中的68个内置函数,按顺序逐个进行了自认为详细的解析.为了方便记忆,将这些内置函数进行了如下分类: 数学运算(7个) 类型转换(24个) 序列操作(8个) 对象操作(7个) 反射操作(8个 ...
- LUOGU P3178 [HAOI2015]树上操作
传送门 解题思路 树链剖分裸题,线段树维护. 代码 #include<iostream> #include<cstdio> #include<cstring> #d ...
- 深入protoBuf
ProtoBuf 官方文档翻译 [翻译] ProtoBuf 官方文档(一)- 开发者指南 [翻译] ProtoBuf 官方文档(二)- 语法指引(proto2) [翻译] ProtoBuf 官方文档( ...
- Django数据库连接丢失问题
问题 在Django中使用mysql偶尔会出现数据库连接丢失的情况,错误通常有如下两种 1. OperationalError: (2006, 'MySQL server has gone away' ...
- LA5713 Qin Shi Huang's National Road System
题目大意:秦始皇要在n个城市之间修筑一条道路使得任意两个城市均可连通.有个道士可以用法力帮忙修一条路.秦始皇希望其他的道路总长B最短且用法术连接的两个城市的人口之和A尽量大,因此下令寻找一个A / B ...
- 常见问题:MongoDB基础知识
常见问题:MongoDB基础知识 ·MongoDB支持哪些平台? ·MongoDB作为托管服务提供吗? ·集合(collection)与表(table)有何不同? ·如何创建数据库(database) ...