对象池

转载 2012年03月26日 16:48:53

对象池

CTimeUtil.h

#ifndef CTIMEUTIL_H
#define CTIMEUTIL_H

#if defined(_MSC_VER)
#include <Windows.h>
#else
#include <sys/time.h>
#include <unistd.h>
#endif

typedef enum TIME_LEV
{
    MISEC_LEV,
    USEC_LEV
};

class CTimeUtil
{
public:
    CTimeUtil(TIME_LEV lev = USEC_LEV) : m_Lev(lev) {};
    ~CTimeUtil(){};

public:
    void  Begin()
    {
#if defined(_MSC_VER)
        QueryPerformanceCounter(&m_TmBegin);
        //time = GetTickCount();
#else
        struct timezone tz;
        gettimeofday(&m_TmBegin , &tz);
#endif
    }

    unsigned int End()
    {
        unsigned int timeuse;
#if defined(_MSC_VER)
        //unsigned int tmend = GetTickCount();
        //return (tmend - m_Time);
        LARGE_INTEGER tmend;
        LARGE_INTEGER tmused;
        QueryPerformanceCounter( &tmend );
        tmused.QuadPart = tmend.QuadPart - m_TmBegin.QuadPart;

        LARGE_INTEGER frequence;
        QueryPerformanceFrequency(&frequence);
        timeuse = (unsigned int)(1000000.0 * tmused.QuadPart / frequence.QuadPart);
#else
        struct timeval tmend;
        struct timezone tz;
        gettimeofday(&tmend , &tz);
        timeuse = 1000000*(tmend.tv_sec-m_TmBegin.tv_sec) + tmend.tv_usec-m_TmBegin.tv_usec;
#endif
        if (m_Lev == MISEC_LEV)
        {
            timeuse /= 1000;
        }
        return timeuse;
    }

private:
    TIME_LEV m_Lev;
#if defined(_MSC_VER)
    LARGE_INTEGER m_TmBegin;
#else
    struct timeval m_TmBegin;
#endif
};
#endif


///ObjectPool.cpp

#include <queue>
#include <vector>
#include <stdexcept>
#include <memory>

#include <string>
#include <iostream>
#include <iterator>
#include <stdio.h>
#include "CTimeUtil.h"
using namespace std;

using std::queue;
using std::vector;

//
// template class ObjectPool
//
// Provides an object pool that can be used with any class that provides a
// default constructor.
//
// The object pool constructor creates a pool of objects, which it hands out
// to clients when requested via the acquireObject() method. When a client is
// finished with the object it calls releaseObject() to put the object back
// into the object pool.
//
// The constructor and destructor on each object in the pool will be called only
// once each for the lifetime of the program, not once per acquisition and release.
//
// The primary use of an object pool is to avoid creating and deleting objects
// repeatedly. The object pool is most suited to applications that use large
// numbers of objects for short periods of time.
//
// For efficiency, the object pool doesn't perform sanity checks.
// Expects the user to release every acquired object exactly once.
// Expects the user to avoid using any objects that he or she has released.
//
// Expects the user not to delete the object pool until every object
// that was acquired has been released. Deleting the object pool invalidates
// any objects that the user had acquired, even if they had not yet been released.
//
template <typename T>
class ObjectPool
{
 public:
  //
  // Creates an object pool with chunkSize objects.
  // Whenever the object pool runs out of objects, chunkSize
  // more objects will be added to the pool. The pool only grows:
  // objects are never removed from the pool (freed), until
  // the pool is destroyed.
  //
  // Throws invalid_argument if chunkSize is <= 0.
  //
  ObjectPool(int chunkSize = kDefaultChunkSize)
    throw(std::invalid_argument, std::bad_alloc);

  //
  // Frees all the allocated objects. Invalidates any objects that have
  // been acquired for use.
  //
  ~ObjectPool();

  //
  // Reserve an object for use. The reference to the object is invalidated
  // if the object pool itself is freed.
  //
  // Clients must not free the object!
  //
  T& acquireObject();

  //
  // Return the object to the pool. Clients must not use the object after
  // it has been returned to the pool.
  //
  void releaseObject(T& obj);

 protected:
  //
  // mFreeList stores the objects that are not currently in use
  // by clients.
  //
  queue<T*> mFreeList;
  //
  // mAllObjects stores pointers to all the objects, in use
  // or not. This vector is needed in order to ensure that all
  // objects are freed properly in the destructor.
  //
  vector<T*> mAllObjects;

  int mChunkSize;
  static const int kDefaultChunkSize = 10;

  //
  // Allocates mChunkSize new objects and adds them
  // to the mFreeList.
  //
  void allocateChunk();
  static void arrayDeleteObject(T* obj);

 private:
  // Prevent assignment and pass-by-value
  ObjectPool(const ObjectPool<T>& src);
  ObjectPool<T>& operator=(const ObjectPool<T>& rhs);
};

template<typename T>
const int ObjectPool<T>::kDefaultChunkSize;

template <typename T>
ObjectPool<T>::ObjectPool(int chunkSize) throw(std::invalid_argument,
    std::bad_alloc) : mChunkSize(chunkSize)
{
    if (mChunkSize <= 0) {
        throw std::invalid_argument("chunk size must be positive");
    }
    // Create mChunkSize objects to start
    allocateChunk();
}

//
// Allocates an array of mChunkSize objects because that's
// more efficient than allocating each of them individually.
// Stores a pointer to the first element of the array in the mAllObjects
// vector. Adds a pointer to each new object to the mFreeList.
//
template <typename T>
void ObjectPool<T>::allocateChunk()
{
    T* newObjects = new T[mChunkSize];
    mAllObjects.push_back(newObjects);
    for (int i = 0; i < mChunkSize; i++)
    {
        mFreeList.push(&newObjects[i]);
    }
}

//
// Freeing function for use in the for_each algorithm in the
// destructor.
//
template<typename T>
void ObjectPool<T>::arrayDeleteObject(T* obj)
{
    delete [] obj;
}

template <typename T>
ObjectPool<T>::~ObjectPool()
{
    // free each of the allocation chunks
    for_each(mAllObjects.begin(), mAllObjects.end(), arrayDeleteObject);
}

template <typename T>
T& ObjectPool<T>::acquireObject()
{
    if (mFreeList.empty()) {
        allocateChunk();
    }
    T* obj = mFreeList.front();
    mFreeList.pop();
    return (*obj);
}

template <typename T>
void ObjectPool<T>::releaseObject(T& obj)
{
    mFreeList.push(&obj);
}


class UserRequest
{
public:
  UserRequest() {/* printf("\nUserRequest...\n" );*/}
  ~UserRequest() {}

  // Methods to populate the request with specific information.
  // Methods to retrieve the request data.
  // (not shown)

protected:
  // data members (not shown)
};

UserRequest& obtainUserRequest(ObjectPool<UserRequest>& pool)
{
  // Obtain a UserRequest object from the pool
  UserRequest& request = pool.acquireObject();

  // populate the request with user input
  // (not shown)

  return (request);
}

void processUserRequest(ObjectPool<UserRequest>& pool, UserRequest& req)
{
  // process the request
  // (not shown)

  // return the request to the pool
  pool.releaseObject(req);
}

#define TEST_MAX_OBJ_COUNT 10000000

int main(int argc, char** argv)
{
  CTimeUtil ut;
  ut.Begin();
  vector<UserRequest*> vec;
  vec.reserve(TEST_MAX_OBJ_COUNT);
  ObjectPool<UserRequest> requestPool(1000);

  // Set up program
  // (not shown)

  int count = TEST_MAX_OBJ_COUNT;


  while ((count--)) {
    UserRequest& req = obtainUserRequest(requestPool);

    vec.push_back(&req);

    //processUserRequest(requestPool, req);
  }
  cout<<"Used Object Pool : time :" << ut.End()<<endl;
    for ( vector<UserRequest*>::iterator it = vec.begin(); it != vec.end(); ++it )
    {
        processUserRequest(requestPool, *(*it));
    }

  cout<<"Used Object Pool : time :" << ut.End()<<endl;

  return (0);
}



一个简单的Java对象池实现——可用来解决SimpleDateFormat的线程安全问题

被SimpleDateFormat的线程安全问题困扰过的人应该不止我一个吧。为了比秒这个类的线程安全,通常我们会有以下两种做法: 每次都new 一个SimpleDateFormat对象,但频繁的创建与...
  • nmgrd
  • nmgrd
  • 2016年06月17日 17:55
  • 1867

Unity3D之对象池(Object Pool)

其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身优化内存和Unity3D Profiler的使用,都很精彩,有兴趣的童鞋可以参考一下。第三篇写了对象池的实现,从简单到难。 ...
  • qq563129582
  • qq563129582
  • 2016年12月18日 22:05
  • 534

Unity3d 单例对象池

原创 单例模式 初学者很容易搞晕,为啥有2种写法,这里顺带着写一下,不是本章的要点。 首先,是继承自MonoBehaviour的单例,需要使用U3D组件和功能可以用这种单例。理解U3D本身单例...
  • u012322710
  • u012322710
  • 2016年11月18日 23:07
  • 1636

Unity3D对象池的理解与小例子

最近在学习Unity3D,在制作一个跑酷Demo的时候,发现不停的初始化障碍物和删除障碍物比较卡,后来研究了一下对象池,整了大半天,总算是明白了。现在记录下来,希望能帮助和我一样的新手,如果有不对的地...
  • Tomato2313
  • Tomato2313
  • 2016年10月29日 10:25
  • 2551

对象池技术

Apache的commons-pool提供了编写对象池的API,将用完的对象返回对象池中以便于下次利用,从而减少了对象创建时间。这对于创建对象相对耗时的应用来说,能够提高应用的性能。  comm...
  • nanmuling
  • nanmuling
  • 2014年07月16日 16:40
  • 711

关于unity对象池的用法

当游戏中需要发射子弹(gameobject)等操作的时候,不停的Instantiate和destroy就会很耗性能,如果又是多人游戏,那多人同时Instantiate和destroy子弹,配置不高的设...
  • liuleitheone
  • liuleitheone
  • 2016年08月04日 10:22
  • 3307

Android中对象池的使用

对象池的使用 在Android开发中经常会发现当日志中出现大量GC时我们的应用常常出现卡顿。这是因为当虚拟机进行垃圾回收操作时应用所有线程都会暂停,完成后恢复。如果出现大量GC操作时主线程频繁暂停就...
  • zuochunsheng
  • zuochunsheng
  • 2017年02月11日 10:28
  • 387

Cocos2dx对象池的一个实现

// // ObjectPool.h // DragonBall // // Created by user on 13-8-22. // // #ifndef __DragonBall__O...
  • ym19860303
  • ym19860303
  • 2013年08月23日 16:49
  • 3425

对象池的优劣

对象池的优点: 复用池中对象, 没有分配内存和创建堆中对象的开销, 没有释放内存和销毁堆中对象的开销, 进而减少垃圾收集器的负担, 避免内存抖动; 不必重复初始化对象状态, 对于比较耗时的constr...
  • kslinabc
  • kslinabc
  • 2016年03月08日 12:38
  • 3575

用C#建立通用对象池[2]

 创建一个接口,用于限定对象池中所保存的对象的基本行为:          public interfac...
  • guanzhongs
  • guanzhongs
  • 2006年03月23日 22:54
  • 3250
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:对象池
举报原因:
原因补充:

(最多只允许输入30个字)