::value >()(f,*iter); } }
Hi all Here is my objectpool implemention which inspired by boost pool. Which have following features. Features: 1.Allocate an object from pre-allocate memory, when free an object just put it back to pool. 2.Call object's contructor at pool memory allocating or get object from pool, or do nothing. 3.Call object's deconstructor when "delete" object if constructor's been calling at "new" object 3.Call object's deconstructor when destroy objectpool if constructor's been calling at memory allocating 4.Can pass an function object to be invoke when "new" object, this can be used as a constructor if object's constructor don't be invokded when "new" object 5.Thread safe can be enable/disable by tempalte parameter 6.Callback can be raw pointer is T is not inherit from enable_shared_from this can be shared_ptr vers vice. There are several tasks need to do, like the allnodesset can be generated at callring of foreach. Delegate memory allocating to allocator, etc.. The whole project and unit test can be found at https://maxsrecyclebin.svn.sourceforge.net/svnroot/maxsrecyclebin/objectpool... Is there any comments? Thanks ////////////////////////////////////////////////////////////////////////////////////// #include <istream> #include <list> #include <boost/shared_ptr.hpp> #include <boost/bind.hpp> #include <set> #include <algorithm> #include <boost/type_traits.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/thread/pthread/mutex.hpp> namespace maxutility { enum InitialType {None,ObjInitial,PoolAllocate}; template <typename T> class DummyCallableObj { public: void operator ()(boost::shared_ptr<T> &ptr) { //do nothing } }; template<bool isthreadsafe> class obthreadlock; template<> class obthreadlock<true> { public: void lock(){obmutex.lock();} bool try_lock(){return obmutex.try_lock();} void unlock(){obmutex.unlock();} private: boost::mutex obmutex; }; template<> class obthreadlock<false> { public: void lock(){}; bool try_lock(){return true;}; void unlock(){}; }; template <typename T,bool isthreadsafe=false,typename InitalFunction=DummyCallableObj<T> > class ObjectPool { #define LOCAL_LOCK boost::lock_guard<obthreadlock<isthreadsafe> > lg(obthreadlock_); protected: /** * @brief Declaration for furture usage **/ typedef T Node; typedef std::list<char *> FRAGMENTTYPE; typedef std::list<Node *> NODELIST; public: ObjectPool(InitialType initialtype=ObjInitial,size_t initialsize=512,size_t maxsize=0) { busyCount=0; this->poolsize=0; this->initialtype=initialtype; this->maxsize=maxsize; extend(initialsize); } ObjectPool(InitalFunction initalFunction=DummyCallableObj<T>(), InitialType initialtype=PoolAllocate, size_t initialsize=512, size_t maxsize=0) //:ObjectPool(initialtype,initialsize,maxsize) //Delegating constructors, c++11 only { busyCount=0; this->poolsize=0; this->initialtype=initialtype; this->maxsize=maxsize; this->initalFunction=initalFunction; extend(initialsize); } ~ObjectPool() { if(0!=busyCount) throw new std::exception(); if(PoolAllocate==initialtype) for(Node *p:allnodes) p->~Node(); for(char *pFragment:fragments) delete pFragment; } virtual boost::shared_ptr<T> create() { LOCAL_LOCK; boost::shared_ptr<T> ptr(static_cast<T*>(getFreeNode()),boost::bind(&ObjectPool<T,isthreadsafe,InitalFunction>::free,this,_1)); initalFunction(ptr); return ptr; } bool empty() { return !busyCount; } size_t size() { return busyCount; } size_t capacity() { return poolsize; } template <typename FUNCTION> void foreach(FUNCTION f) { LOCAL_LOCK; NODELIST freenodes=this->freenodes; //make a local copy freenodes.sort(); NODELIST busynodes(allnodes.size()); typename NODELIST::iterator busynodesend=std::set_difference( allnodes.begin(),allnodes.end(),freenodes.begin(),freenodes.end(),busynodes.begin() ); for(typename NODELIST::iterator iter=busynodes.begin(); iter!=busynodesend; iter++) { invokeFunction<FUNCTION,Node, boost::is_base_of<boost::enable_shared_from_this<Node>,Node protected: template<typename _Function,typename N,bool isuseshareptr> class invokeFunction; template<typename _Function,typename N> class invokeFunction<_Function,N,false> { public: void operator ()(_Function __f,N *p) { __f(p); } }; template<typename _Function,typename N> class invokeFunction<_Function,N,true> { public: void operator ()(_Function __f,N *p) { boost::shared_ptr<N> ptr=p->shared_from_this(); __f(ptr); } }; protected: void free(T *p) { LOCAL_LOCK; if(!p) return; destroyObj(static_cast<Node*>(p),ObjInitial); //removeBusyNode(static_cast<Node*>(p)); freenodes.push_back(static_cast<Node*>(p)); busyCount--; } Node *getFreeNode() { Node *ptr=nullptr; if(freenodes.empty()) //no new free node if(!extend()) //try to extend return ptr; //false ptr=freenodes.front(); //now it must contain free node freenodes.pop_front(); constructObj(ptr,ObjInitial); busyCount++; return ptr; } bool extend(size_t size=0) { if((0!=maxsize&&poolsize>=maxsize&&poolsize!=0) ) return false; //we reach the maximum size //poolsize=0 first allocation //size=0 extend twice size of current size //poolsize=size=0 we got a problem size_t extSize=((0==poolsize)?size:2*poolsize); char *pFragment=new char[extSize*sizeof(Node)]; if(!pFragment) return false; fragments.push_back(pFragment); poolsize+=extSize; for(Node *p=(Node*)pFragment; extSize--; p++) { constructObj(p,PoolAllocate); freenodes.push_back(p); allnodes.push_back(p); } allnodes.sort(); return true; } void constructObj(Node *p,InitialType phase) { if(phase==initialtype) ::new(p)Node; } void destroyObj(Node *p,InitialType phase) { if(phase==initialtype) p->~Node(); } size_t poolsize; InitialType initialtype; size_t maxsize; FRAGMENTTYPE fragments; NODELIST freenodes; NODELIST allnodes; size_t busyCount; InitalFunction initalFunction; obthreadlock<isthreadsafe> obthreadlock_; }; };