`
hyshucom
  • 浏览: 811231 次
文章分类
社区版块
存档分类
最新评论

池化技术 漫谈

 
阅读更多

原文地址:http://blog.csdn.net/magictong/article/details/3143947

池化技术 - 简单点来说,就是提前保存大量的资源,以备不时之需,O(∩_∩)O,对于线程,内存,oracle的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果你的程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响你整个程序性能的瓶颈。池化技术主要有线程池,内存池,连接池,对象池等等,对象池就是提前创建很多对象,将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,连接池比较典型的有oracle的连接池,了解不深。

下面主要谈谈线程池和内存池,因为这两种技术的通用性和实用性也是比较强的,描述语言C++,其实线程池的话用什么实现都可以。

先来谈谈线程池技术,线程池的框架早就有先辈给我们想好了,也就不用我们去冥思苦想了,我们要做的就是把先辈的想法发现即可。

其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。可能你也许会问:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了?这也许是个不错的方法,因为它能使得你编写代码相对容易一些,但你却忽略了一个重要的问题?性能!尤其是对于服务器程序尤为重要,服务器程序会先初始化很多线程在那里等待,当有客户连接时,就激活其中的一个线程来处理客户请求,对于不支持动态增加的线程池,如果没有等待线程,客户就必学等待,而对于能动态增加线程的线程池,则可以像线程池中新加一个线程。

下面是一个用c++实现的线程池,支持动态增减线程数量:

  1. /*-------------------------------------------------------------------------
  2. //文件名:KThreadPool.h
  3. //创建者:magicTong
  4. //创建时间:2008-10-2315:02:31
  5. //功能描述:线程池声明
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #ifndef__KTHREADPOOL_H__
  10. #define__KTHREADPOOL_H__
  11. //-------------------------------------------------------------------------
  12. #include<windows.h>
  13. #include<list>
  14. usingnamespacestd;
  15. //线程函数指针定义
  16. typedefDWORD(WINAPI*PTHREAD_FUNC_EX)(LPVOIDlpThreadParameter);
  17. //线程状态枚举
  18. typedefenum_enumKThreadStatus
  19. {
  20. THREADRUN,//运行
  21. THREADPAUSE,//暂停
  22. }
  23. KThreadStatus;
  24. //-------------------------------------------------------------------------
  25. //类名:KThread
  26. //功能:线程类,可动态更换执行函数
  27. //附注:
  28. //-------------------------------------------------------------------------
  29. classKThread
  30. {
  31. public:
  32. //构造
  33. KThread();
  34. //析构
  35. ~KThread();
  36. //-------------------------------------------------------------------------
  37. //函数:Init
  38. //功能:初始化函数
  39. //返回值:bool
  40. //附注:
  41. //-------------------------------------------------------------------------
  42. boolInit();
  43. //-------------------------------------------------------------------------
  44. //函数:Run
  45. //功能:运行线程
  46. //返回值:bool
  47. //附注:
  48. //-------------------------------------------------------------------------
  49. boolRun();
  50. //-------------------------------------------------------------------------
  51. //函数:Pause
  52. //功能:暂停线程
  53. //返回值:bool
  54. //附注:
  55. //-------------------------------------------------------------------------
  56. boolPause();
  57. //-------------------------------------------------------------------------
  58. //函数:Join
  59. //功能:调用Join的线程将阻塞,直到该线程执行完毕
  60. //返回值:void
  61. //附注:
  62. //-------------------------------------------------------------------------
  63. voidJoin();
  64. //-------------------------------------------------------------------------
  65. //函数:SetProc
  66. //功能:设置线程运行的函数,和要传给线程的参数
  67. //返回值:void
  68. //参数:PTHREAD_FUNC_EXproc
  69. //参数:void*lpParam
  70. //附注:
  71. //-------------------------------------------------------------------------
  72. voidSetProc(PTHREAD_FUNC_EXproc,void*lpParam);
  73. protected:
  74. KThread(KThread&){}
  75. //线程实际运行的函数
  76. staticDWORDWINAPIRealThreadProc(void*lpParam);
  77. friendclassKThreadPool;
  78. protected:
  79. structKThreadParam
  80. {
  81. PTHREAD_FUNC_EXproc;//用户线程函数
  82. void*lpParam;//用户线程参数
  83. KThread*pThread;//线程类对象
  84. };
  85. HANDLEm_hThread;
  86. DWORDm_id;
  87. KThreadParamm_param;
  88. KThreadStatusm_status;
  89. HANDLEm_hEvt;
  90. HANDLEm_hMtx;
  91. };
  92. //-------------------------------------------------------------------------
  93. //类名:KThreadPool
  94. //功能:线程池类声明
  95. //附注:
  96. //-------------------------------------------------------------------------
  97. classKThreadPool
  98. {
  99. public:
  100. //构造,initNum初始情况线程数量
  101. KThreadPool(intinitNum);
  102. //析构
  103. ~KThreadPool();
  104. //-------------------------------------------------------------------------
  105. //函数:DoWork
  106. //功能:申请线程进行工作,proc工作函数,lpParam工作函数参数,run是否立即运行,返回线程ID
  107. //返回值:DWORD
  108. //参数:PTHREAD_FUNC_EXproc
  109. //参数:void*lpParam
  110. //参数:boolrun=true
  111. //附注:
  112. //-------------------------------------------------------------------------
  113. DWORDDoWork(PTHREAD_FUNC_EXproc,void*lpParam,boolrun=true);
  114. //-------------------------------------------------------------------------
  115. //函数:Run
  116. //功能:运行线程,id线程ID
  117. //返回值:bool
  118. //参数:DWORDid
  119. //附注:
  120. //-------------------------------------------------------------------------
  121. boolRun(DWORDid);
  122. //-------------------------------------------------------------------------
  123. //函数:Pause
  124. //功能:暂停运行线程,id线程ID
  125. //返回值:bool
  126. //参数:DWORDid
  127. //附注:
  128. //-------------------------------------------------------------------------
  129. boolPause(DWORDid);
  130. //调整线程池大小为size,返回调整后线程池大小
  131. unsignedSetSize(unsignedsize);
  132. protected:
  133. list<KThread*>m_lst;
  134. };

实现:

  1. /*-------------------------------------------------------------------------
  2. //文件名:KThreadPool.cpp
  3. //创建者:magicTong
  4. //创建时间:2008-10-2315:02:22
  5. //功能描述:线程池定义
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #include"stdafx.h"
  10. #include"KThreadPool.h"
  11. //-------------------------------------------------------------------------
  12. //-------------------------------------------------------------------------
  13. //KThread类定义开始
  14. //-------------------------------------------------------------------------
  15. KThread::KThread():m_hThread(NULL),
  16. m_status(THREADPAUSE),
  17. m_hEvt(0),
  18. m_hMtx(0)
  19. {
  20. }
  21. KThread::~KThread()
  22. {
  23. ::CloseHandle(m_hMtx);
  24. if(::TerminateThread(m_hThread,-1)==0)
  25. return;
  26. }
  27. boolKThread::Init()
  28. {
  29. m_hThread=::CreateThread(
  30. 0,
  31. 0,
  32. (PTHREAD_FUNC_EX)(KThread::RealThreadProc),
  33. (void*)&m_param,
  34. CREATE_SUSPENDED,
  35. &m_id);
  36. //创建线程失败
  37. if(NULL==m_hThread)
  38. {
  39. returnfalse;
  40. }
  41. m_param.proc=NULL;
  42. m_param.lpParam=NULL;
  43. m_param.pThread=this;
  44. //自动复位
  45. m_hEvt=::CreateEvent(0,FALSE,FALSE,0);
  46. if(m_hEvt==0)
  47. {
  48. ::CloseHandle(m_hThread);
  49. returnfalse;
  50. }
  51. m_hMtx=::CreateMutex(0,0,0);
  52. if(m_hMtx==0)
  53. {
  54. ::CloseHandle(m_hEvt);
  55. ::CloseHandle(m_hThread);
  56. returnfalse;
  57. }
  58. returntrue;
  59. }
  60. boolKThread::Run()
  61. {
  62. ::WaitForSingleObject(m_hMtx,INFINITE);
  63. if(m_status==THREADPAUSE)
  64. if(::ResumeThread(m_hThread)==-1)
  65. {
  66. ::ReleaseMutex(m_hMtx);
  67. returnfalse;
  68. }
  69. m_status=THREADRUN;
  70. ::ReleaseMutex(m_hMtx);
  71. returntrue;
  72. }
  73. boolKThread::Pause()
  74. {
  75. ::WaitForSingleObject(m_hMtx,INFINITE);
  76. if(m_status==THREADRUN)
  77. if(::SuspendThread(m_hThread)==-1)
  78. {
  79. ::ReleaseMutex(m_hMtx);
  80. returnfalse;
  81. }
  82. m_status=THREADPAUSE;
  83. ::ReleaseMutex(m_hMtx);
  84. returntrue;
  85. }
  86. voidKThread::Join()
  87. {
  88. ::WaitForSingleObject(m_hEvt,INFINITE);
  89. }
  90. voidKThread::SetProc(PTHREAD_FUNC_EXproc,void*lpParam)
  91. {
  92. ::WaitForSingleObject(m_hMtx,INFINITE);
  93. m_param.proc=proc;
  94. m_param.lpParam=lpParam;
  95. ::ReleaseMutex(m_hMtx);
  96. }
  97. DWORDWINAPIKThread::RealThreadProc(void*lpParam)
  98. {
  99. PTHREAD_FUNC_EXproc;
  100. KThreadParam*pp=(KThreadParam*)lpParam;
  101. while(true)
  102. {
  103. proc=pp->proc;
  104. if(proc)
  105. (*proc)(pp->lpParam);
  106. pp->proc=NULL;
  107. pp->lpParam=NULL;
  108. pp->pThread->Pause();
  109. ::SetEvent(pp->pThread->m_hEvt);
  110. }
  111. }
  112. //-------------------------------------------------------------------------
  113. //KThread类定义结束
  114. //-------------------------------------------------------------------------
  115. //-------------------------------------------------------------------------
  116. //KThreadPool类定义开始
  117. //-------------------------------------------------------------------------
  118. KThreadPool::KThreadPool(intinitNum)
  119. {
  120. KThread*pt;
  121. for(inti=0;i<initNum;i++)
  122. {
  123. pt=newKThread;
  124. if(pt->Init())
  125. m_lst.push_back(pt);
  126. }
  127. }
  128. KThreadPool::~KThreadPool()
  129. {
  130. list<KThread*>::iteratoritBegin=m_lst.begin();
  131. list<KThread*>::iteratoritEnd=m_lst.end();
  132. for(;itBegin!=itEnd;itBegin++)
  133. {
  134. delete(*itBegin);
  135. }
  136. }
  137. DWORDKThreadPool::DoWork(LPTHREAD_START_ROUTINEproc,void*lpParam,boolrun)
  138. {
  139. list<KThread*>::iteratoritBegin=m_lst.begin();
  140. list<KThread*>::iteratoritEnd=m_lst.end();
  141. for(;itBegin!=itEnd;itBegin++)
  142. {
  143. if((*itBegin)->m_param.proc==NULL&&(*itBegin)->m_status==THREADPAUSE)
  144. {
  145. (*itBegin)->SetProc(proc,lpParam);
  146. //立即运行
  147. if(run)
  148. (*itBegin)->Run();
  149. return(*itBegin)->m_id;
  150. }
  151. }
  152. //没有空闲线程,新建一个新的线程,加入链表
  153. KThread*pt=newKThread;
  154. if(pt->Init())
  155. m_lst.push_back(pt);
  156. pt->SetProc(proc,lpParam);
  157. if(run)
  158. pt->Run();
  159. returnpt->m_id;
  160. }
  161. boolKThreadPool::Run(DWORDid)
  162. {
  163. list<KThread*>::iteratoritBegin=m_lst.begin();
  164. list<KThread*>::iteratoritEnd=m_lst.end();
  165. for(;itBegin!=itEnd;itBegin++)
  166. {
  167. if((*itBegin)->m_id==id)
  168. return((*itBegin)->Run());
  169. }
  170. returnfalse;
  171. }
  172. boolKThreadPool::Pause(DWORDid)
  173. {
  174. list<KThread*>::iteratoritBegin=m_lst.begin();
  175. list<KThread*>::iteratoritEnd=m_lst.end();
  176. for(;itBegin!=itEnd;itBegin++)
  177. {
  178. if((*itBegin)->m_id==id)
  179. return((*itBegin)->Pause());
  180. }
  181. returnfalse;
  182. }
  183. //-------------------------------------------------------------------------
  184. //函数:KThreadPool::SetSize
  185. //功能:修改线程池的大小
  186. //返回值:unsigned
  187. //参数:unsignedsize
  188. //附注:如果小缩小线程池大小,谨慎使用
  189. //-------------------------------------------------------------------------
  190. unsignedKThreadPool::SetSize(unsignedsize)
  191. {
  192. unsignednowsize=m_lst.size();
  193. if(nowsize<=size)
  194. {
  195. KThread*pt;
  196. unsignedinc=size-nowsize;
  197. for(unsignedi=0;i<inc;i++)
  198. {
  199. pt=newKThread;
  200. if(pt->Init())
  201. {
  202. m_lst.push_back(pt);
  203. }
  204. }
  205. returnsize;
  206. }
  207. else
  208. {
  209. unsigneddec=nowsize-size;
  210. list<KThread*>::iteratorit=m_lst.begin();
  211. list<KThread*>::iteratorite=m_lst.end();
  212. list<KThread*>::iteratoritemp;
  213. unsignedi=0;
  214. for(;it!=ite&&i<dec;)
  215. {
  216. if((*it)->m_status==THREADPAUSE)
  217. {
  218. itemp=it++;
  219. delete((*itemp));
  220. m_lst.erase(itemp);
  221. i++;
  222. continue;
  223. }
  224. it++;
  225. }
  226. ::Sleep(100*i);
  227. returnm_lst.size();
  228. }
  229. }
  230. //-------------------------------------------------------------------------
  231. //KThreadPool类定义结束
  232. //-------------------------------------------------------------------------

使用:

要定义一个线程函数,然后再将该函数和线程数量设置到内存池中,测试代码如下:

  1. DWORDWINAPIthreadFunc(LPVOIDlpThreadParam);
  2. voidCKThreadPoolExDlg::OnBtnCreate()
  3. {
  4. statici=0;
  5. if(!m_pThreadPool)
  6. {
  7. m_pThreadPool=newKThreadPool(1);
  8. }
  9. m_pThreadPool->DoWork(threadFunc,this,true);
  10. i++;
  11. if(i==4)
  12. {
  13. m_pThreadPool->SetSize(10);
  14. }
  15. }
  16. voidCKThreadPoolExDlg::DoSomething()
  17. {
  18. //MessageBox("O(∩_∩)O哈哈~");
  19. while(true)
  20. {
  21. ::EnterCriticalSection(&m_cs);
  22. DWORDid=GetCurrentThreadId();
  23. CStringcstr;
  24. cstr.Format("线程%d正在运行...",id);
  25. m_listInfo.InsertItem(m_listInfo.GetItemCount(),cstr);
  26. ::LeaveCriticalSection(&m_cs);
  27. ::Sleep(400);
  28. }
  29. }
  30. DWORDWINAPIthreadFunc(LPVOIDlpThreadParam)
  31. {
  32. CKThreadPoolExDlg*pdlg=(CKThreadPoolExDlg*)lpThreadParam;
  33. pdlg->DoSomething();
  34. return0;
  35. }

代码的详细注释我就不写了,想弄懂原理的还是好好研究下再使用,我不保证里面没有BUG。

再来看看内存池的原理,我下面的参考资料里面有几篇文章讲得不错,想了解原理的可以去看看。

如何更好的管理在应用程序中内存的使用,同时提高内存使用的效率,这是值得每一个开发人员深思的问题。内存池(Memory pool)提供了一种比较可行的解决方案。首先是创建内存池。这个过程的主要任务是预先分配足够大的内存,形成一个初步的“内存池”。分配内存,也就是用户请求内存时,会返回内存池中一块空闲的内存,并将其标志置为已使用,当然具体细节和方法有很多。释放内存时,不是真正地调用free或是delete的过程,而是把内存放回内存池的过程。在把内存放入内存池的同时,要把标志位置为空闲。最后在应用程序结束时,要把内存池销毁。这里主要做的工作就是把内存池中的每一块内存释放。

使用内存池的好处:

1、减少了内存碎片的产生。这个可以从创建内存池的过程中看出。我们在创建内存池时,分配的都是一块块比较整的内存块,这样可以减少内存碎片的产生。

2、提高了内存的使用效率。这个可以从分配内存和释放内存的过程中看出。每次的分配与释放并不是去调用系统提供的函数或是操作符去操作实际的内存,而是在复用内存池中的内存。

缺点就是很有可能会造成内存的浪费,原因也很明显,开始分配了一大块内存,不是全部都用得到的。

针对内存池,这里有两个实现,头一个很简单,用到了STL的队列来管理内存池指针,而且如果分配的内存没有显示的归还给内存池的话,即使内存池销毁的时候,这块内存也不会被销毁,就会有内存泄露,当然这个程序还可以改进,另外一个程序是根据《C++应用程序性能优化》中提到的一种方法来实现的,程序见下面:

简单实现(还有很大的改进余地):

  1. /*-------------------------------------------------------------------------
  2. //文件名:MemPool.h
  3. //创建者:magicTong
  4. //创建时间:2008-10-2417:50:00
  5. //功能描述:一个简单的内存池实现
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #ifndef__MEMPOOL_H__
  10. #define__MEMPOOL_H__
  11. //-------------------------------------------------------------------------
  12. #include<queue>
  13. #defineMemoryBlockSize1024
  14. #defineMemoryBlockNum20
  15. classKMemPool
  16. {
  17. public:
  18. //构造
  19. explicitKMemPool(inta_memoryBlockNum=MemoryBlockNum,
  20. inta_memoryBlockSize=MemoryBlockSize);
  21. //析构
  22. virtual~KMemPool();
  23. //两个主要的操作
  24. intNewMemBuf(char*&a_recvBuff);
  25. intDelMemBuf(char*a_recvBuff);
  26. private:
  27. void_initMemPool(inta_memoryBlockNum,inta_memoryBlockSize);
  28. std::queue<char*>m_memPool;
  29. };
  30. //-------------------------------------------------------------------------
  31. //$Log:$
  32. #endif/*__MEMPOOL_H__*/

实现:

  1. /*-------------------------------------------------------------------------
  2. //文件名:MemPool.cpp
  3. //创建者:magicTong
  4. //创建时间:2008-10-2417:50:19
  5. //功能描述:简单内存池实现
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #include"stdafx.h"
  10. #include"MemPool.h"
  11. //-------------------------------------------------------------------------
  12. //构造
  13. KMemPool::KMemPool(inta_memoryBlockNum/*=MemoryBlockNum*/,
  14. inta_memoryBlockSize/*=MemoryBlockSize*/)
  15. {
  16. _initMemPool(a_memoryBlockNum,a_memoryBlockSize);
  17. }
  18. //析构
  19. KMemPool::~KMemPool()
  20. {
  21. char*l_tempBuff=NULL;
  22. while(!m_memPool.empty())
  23. {
  24. l_tempBuff=m_memPool.front();
  25. m_memPool.pop();
  26. if(l_tempBuff)
  27. {
  28. //回收
  29. delete[]l_tempBuff;
  30. l_tempBuff=NULL;
  31. }
  32. }
  33. }
  34. //-------------------------------------------------------------------------
  35. //函数:KMemPool::_initMemPool
  36. //功能:
  37. //返回值:void
  38. //参数:inta_memoryBlockNum
  39. //参数:inta_memoryBlockSize
  40. //附注:
  41. //-------------------------------------------------------------------------
  42. voidKMemPool::_initMemPool(inta_memoryBlockNum,inta_memoryBlockSize)
  43. {
  44. for(inti=0;i<a_memoryBlockNum;++i)
  45. {
  46. char*l_tempBuff=newchar[a_memoryBlockSize];
  47. if(l_tempBuff==NULL)
  48. continue;
  49. m_memPool.push(l_tempBuff);
  50. }
  51. }
  52. //-------------------------------------------------------------------------
  53. //函数:KMemPool::NewMemBuf
  54. //功能:申请一块内存,如果内存池空了,这个时候应该再像系统申请,并且在
  55. //类初始化的时候,加一个增量的变量,也可以提供这样的接口,这里为
  56. //了简单就没有这么做了,只是为了说明问题而已。
  57. //返回值:int
  58. //参数:char*&a_memoryBuff
  59. //附注:如果成功返回0,如果失败返回-1
  60. //-------------------------------------------------------------------------
  61. intKMemPool::NewMemBuf(char*&a_memoryBuff)
  62. {
  63. //如果内存池已空,这个时候正确的做法应该是
  64. //重新申请大块内存
  65. if(m_memPool.empty())
  66. {
  67. _initMemPool(MemoryBlockNum,MemoryBlockSize);
  68. }
  69. a_memoryBuff=m_memPool.front();
  70. m_memPool.pop();
  71. if(a_memoryBuff==NULL)
  72. return-1;
  73. return0;
  74. }
  75. //-------------------------------------------------------------------------
  76. //函数:KMemPool::DelMemBuf
  77. //功能:回收内存,将其放回队列中
  78. //返回值:int
  79. //参数:char*a_memoryBuff
  80. //附注:
  81. //-------------------------------------------------------------------------
  82. intKMemPool::DelMemBuf(char*a_memoryBuff)
  83. {
  84. m_memPool.push(a_memoryBuff);
  85. return0;
  86. }
  87. //-------------------------------------------------------------------------
  88. //$Log:$

根据《C++应用程序性能优化》实现代码如下:

  1. /*-------------------------------------------------------------------------
  2. //文件名:MemPoolEx.h
  3. //创建者:magicTong
  4. //创建时间:2008-10-2417:49:33
  5. //功能描述:
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #ifndef__MEMPOOLEX_H__
  10. #define__MEMPOOLEX_H__
  11. //-------------------------------------------------------------------------
  12. #include<Windows.h>
  13. #defineMEMPOOL_ALIGNMENT4
  14. classKMemBlock
  15. {
  16. public:
  17. KMemBlock(USHORTnTypes=1,USHORTnUnitSize=0);
  18. virtual~KMemBlock();
  19. voidoperatordelete(void*p,size_t);
  20. void*operatornew(size_t,USHORTnTypes,USHORTnUnitSize);
  21. public:
  22. USHORTnSize;//内存块的大小每个小块所占内存*小块个数
  23. USHORTnFree;//空闲块数
  24. USHORTnFirst;//第一个空闲块
  25. //USHORTnDummyAlign1;
  26. KMemBlock*pNext;//下一个Block
  27. charaData[1];//数据的初始位置
  28. };
  29. classKMemPoolEx
  30. {
  31. public:
  32. KMemPoolEx(USHORTuUnitSize,USHORTuInitSize,USHORTuGrowSize);
  33. virtual~KMemPoolEx();
  34. void*Alloc();
  35. voidFree(void*pFree);
  36. private:
  37. void_FreeMemeoryBlock(KMemBlock*pMyBlock);
  38. KMemBlock*pBlock;//第一个block的指针
  39. USHORTnUnitSize;//每个小内存块的字节数
  40. USHORTnInitSize;//初始的Block的内存块数目
  41. USHORTnGrowSize;//增加的Block的内存块数目
  42. };
  43. //-------------------------------------------------------------------------
  44. //$Log:$
  45. #endif/*__MEMPOOLEX_H__*/

实现部分:

  1. /*-------------------------------------------------------------------------
  2. //文件名:MemPoolEx.cpp
  3. //创建者:magicTong
  4. //创建时间:2008-10-2417:49:45
  5. //功能描述:
  6. //
  7. //$Id:$
  8. //-----------------------------------------------------------------------*/
  9. #include"stdafx.h"
  10. #include"MemPoolEx.h"
  11. //-------------------------------------------------------------------------
  12. //构造
  13. KMemBlock::KMemBlock(USHORTnTypes,USHORTnUnitSize)
  14. {
  15. nFree=nTypes-1;
  16. pNext=NULL;
  17. nSize=nTypes*nUnitSize;
  18. nFirst=1;
  19. char*pData=aData;
  20. for(USHORTi=1;i<nTypes;i++)
  21. {
  22. *(USHORT*)pData=i;
  23. pData+=nUnitSize;
  24. }
  25. }
  26. //析构
  27. KMemBlock::~KMemBlock()
  28. {
  29. }
  30. //-------------------------------------------------------------------------
  31. //函数:KMemBlock::operatornew
  32. //功能:
  33. //返回值:void*
  34. //参数:size_t
  35. //参数:USHORTnTypes
  36. //参数:USHORTnUnitSize
  37. //附注:
  38. //-------------------------------------------------------------------------
  39. void*KMemBlock::operatornew(size_t,USHORTnTypes,USHORTnUnitSize)
  40. {
  41. return::operatornew(sizeof(KMemBlock)+nTypes*nUnitSize);
  42. }
  43. //-------------------------------------------------------------------------
  44. //函数:KMemBlock::operatordelete
  45. //功能:
  46. //返回值:void
  47. //参数:void*p
  48. //参数:size_t
  49. //附注:
  50. //-------------------------------------------------------------------------
  51. voidKMemBlock::operatordelete(void*p,size_t)
  52. {
  53. ::operatordelete(p);
  54. }
  55. //-------------------------------------------------------------------------
  56. //线程池定义
  57. //-------------------------------------------------------------------------
  58. //构造
  59. //_uUnitSize每个小内存块的字节数
  60. //_uInitSize是初始的Block的内存块数目
  61. //_uGrowSize增加的Block的内存块数目
  62. KMemPoolEx::KMemPoolEx(USHORT_uUnitSize,USHORT_uInitSize,USHORT_uGrowSize)
  63. {
  64. pBlock=NULL;
  65. nInitSize=_uInitSize;
  66. nGrowSize=_uGrowSize;
  67. if(_uUnitSize<=2)
  68. nUnitSize=2;
  69. elseif(_uUnitSize>2&&_uUnitSize<=4)
  70. nUnitSize=4;
  71. else
  72. {
  73. if(_uUnitSize%MEMPOOL_ALIGNMENT==0)
  74. nUnitSize=_uUnitSize;
  75. else
  76. nUnitSize=(_uUnitSize/MEMPOOL_ALIGNMENT+1)*MEMPOOL_ALIGNMENT;
  77. }
  78. }
  79. //析构
  80. KMemPoolEx::~KMemPoolEx()
  81. {
  82. KMemBlock*pMyBlock=pBlock;
  83. if(pBlock)
  84. _FreeMemeoryBlock(pMyBlock);
  85. }
  86. //-------------------------------------------------------------------------
  87. //函数:KMemPool::_FreeMemeoryBlock
  88. //功能:递归释放内存
  89. //返回值:void
  90. //参数:KMemBlock*pMyBlock
  91. //附注:其实这个地方没必要使用递归,迭代实现很容易
  92. //-------------------------------------------------------------------------
  93. voidKMemPoolEx::_FreeMemeoryBlock(KMemBlock*pMyBlock)
  94. {
  95. if(pMyBlock->pNext)
  96. _FreeMemeoryBlock(pMyBlock->pNext);
  97. deletepMyBlock;
  98. }
  99. //-------------------------------------------------------------------------
  100. //函数:KMemPoolEx::Alloc
  101. //功能:申请内存
  102. //返回值:void*
  103. //附注:
  104. //-------------------------------------------------------------------------
  105. void*KMemPoolEx::Alloc()
  106. {
  107. if(!pBlock)
  108. {
  109. //如果是第一次申请
  110. pBlock=new(nInitSize,nUnitSize)KMemBlock(nInitSize,nUnitSize);
  111. returnpBlock->aData;
  112. }
  113. //如果不是第一次申请
  114. KMemBlock*pMyBlock=pBlock;
  115. while(pMyBlock&&!pMyBlock->nFree)
  116. pMyBlock=pMyBlock->pNext;
  117. //接下来的两种情况:1.找到有空闲块的block2.找不到
  118. void*retval;
  119. //找到了空闲块
  120. if(pMyBlock)
  121. {
  122. pMyBlock->nFree--;
  123. retval=pMyBlock->aData+nUnitSize*pMyBlock->nFirst;
  124. pMyBlock->nFirst=*((USHORT*)retval);
  125. returnretval;
  126. }
  127. //没有找到空闲块,要重新申请
  128. else
  129. {
  130. if(!nGrowSize)
  131. returnNULL;
  132. KMemBlock*newBlock=new(nGrowSize,nUnitSize)KMemBlock(nGrowSize,nUnitSize);
  133. if(!newBlock)
  134. returnNULL;
  135. newBlock->pNext=pBlock;
  136. pBlock=newBlock;
  137. return(void*)(newBlock->aData);
  138. }
  139. returnNULL;
  140. }
  141. //-------------------------------------------------------------------------
  142. //函数:KMemPoolEx::Free
  143. //功能:释放内存
  144. //返回值:void
  145. //参数:void*pFree
  146. //附注:释放内存时,并不真正的归还给堆,而且是回收到内存池中
  147. //-------------------------------------------------------------------------
  148. voidKMemPoolEx::Free(void*pFree)
  149. {
  150. KMemBlock*pMyBlock=pBlock;
  151. KMemBlock*pPreBlock=NULL;//pMyBlock指向Block的前一个Block,用于设置pNext
  152. //如果要求释放的内存并不是内存池里面的内存,则直接返回,不予释放
  153. while((ULONG)pFree<(ULONG)pMyBlock->aData||(ULONG)pFree>(ULONG)(pMyBlock->aData+pMyBlock->nSize))
  154. {
  155. pPreBlock=pMyBlock;
  156. pMyBlock=pMyBlock->pNext;
  157. if(!pMyBlock)
  158. return;
  159. }
  160. //是内存池里面分配出去的,回收到内存池,并不真正归还给堆
  161. if(pMyBlock)
  162. {
  163. pMyBlock->nFree++;
  164. *((USHORT*)pFree)=pMyBlock->nFirst;
  165. pMyBlock->nFirst=(USHORT)(((ULONG)pFree-(ULONG)pMyBlock->aData)/nUnitSize);
  166. if(pMyBlock->nFree*nUnitSize==pMyBlock->nSize)//如果全是自由块
  167. {
  168. if(!pMyBlock->pNext)//如果这是最后一个block,则将其释放
  169. {
  170. deletepMyBlock;//释放
  171. if(pPreBlock)
  172. pPreBlock->pNext=NULL;//设置上一块的pNext指向NULL
  173. else
  174. pBlock=NULL;
  175. }
  176. }
  177. }
  178. }
  179. //-------------------------------------------------------------------------
  180. //$Log:$

数据库连接池是因为,初始化一个数据库连接是非常消耗系统资源的,因此就在程序开始阶段进行数据库的批量连接,然后把这些连接保存下来,等到要使用的时候才拿出来使用,使用完了再放入连接池中。了解不深就不多说了。

参考资料:

CSDN博客:许式伟 著内存池(MemPool)技术详解http://blog.csdn.net/xushiweizh/archive/2006/11/22/1402967.aspx

IBM技术文档:内存池http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html?ca=drs-cn

Java中数据库连接池原理机制讲解:http://www.68design.net/Development/JSP/20703-1.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics