对象池
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);
}