特别声明:
建议使用google游览器,火狐也可以
论坛处于测试阶段,一切资料都为测试资料,在论坛正式运行的时候,会尽量保存网友的劳动成果!
HelloWorld论坛秉持互惠互利,共同学习与进步,一个人的梦想大家实现的理想,一直坚持着,望广大网友多多支持,提供宝贵意见
来论坛做什么?
可以先转载你平时学习查找的资料(先论坛查找),自己可以写写体会
把平时碰到的问题,如何解决可以先记录在论坛,以备后来的人学习
可以和会员一起参加一些开源项目的学习,汉化,推广,甚至可以加入团队
|
|
看了ACE_Dynamic_Cached_Allocator,以为是实现不定长数据分配的,原来ACE_Cached_Allocator实质是一个东西,但是现实当中,我们的内存一般使用是固定的,也足可以满足要求。 现在我们设计一款不定长,不定量的内存分配器。 ACE_Message_Block 构造中,使用了三个分配器,Allocator_stratey,data_block_allocator,message_block_allocator,这三个分配器是分别为ACE_Message_Block对象,ACE_Data_Block对象,以及data_block指向的内存。sizeof(ACE_Message_Block)=40,sizeof(ACE_Data_Block) = 40,也许你要使用ACE_Message_Block的基类,但是他们大小差不多,所以我们可以用较大内存的定长的分配器来解决。至于消息(char*),我们这里假设数据不会大于S_BUFSIZ=1024的3倍。其中1倍比较多,二倍,三倍很少。 我们将要实现这样一个类。 1.进行3级分配,你可以很容易改成其他级别。分别为一级:ACE_Message_Block,ACE_Data_Block,或者其基类,因为内存大小差距不大。二级:S_BUFSIZ的1倍,主要给数据使用,这个比较多使用,我们独立出来。三级:3倍的S_BUFSIZ,这种情况就不多了,但是,还是不能忽视。至于3倍以上的情况,我们下篇文章考虑。我们设定一次申请个数。 2、我们参考[原创]ACE内存分配——定长数据分配(一),里面的模板给我们实现提供了思路,一个管理类,下面很多分配器,实现动态分配。但是里面的模板改变了接口,这样实现不友好。 3、我们参考[原创]ACE内存分配——定长数据分配(二),里面的HwCachedMemPoolNodeg给我们实现提供了办法。 #if (defined HW_ACE) && (defined HW_ACE_ALLOCATOR) //使用自定义内存管理 #ifndef _H_hwnet_block_allocator_ #define _H_hwnet_block_allocator_ #include "ace/Malloc.h" #include <ace/Malloc_T.h> namespace hwnet { template <class T, class ACE_LOCK> class CachedAllocator; template <class T, class ACE_LOCK> class DateNode { public: DateNode<T, ACE_LOCK>(CachedAllocator<T, ACE_LOCK>* pParent) : m_pParent(pParent) { assert(m_pParent); } /// Return the address of free memory. void* addr (void) { return &m_bDate; } /// Get the next DateNode in a list. DateNode<T, ACE_LOCK> *get_next (void) { return next_; } /// Set the next DateNode. void set_next (DateNode<T, ACE_LOCK> *ptr) { next_ = ptr; } private: CachedAllocator<T, ACE_LOCK>* m_pParent; union { char m_bDate[sizeof(T)]; /** * Since memory is not used when placed in a free list, * we can use it to maintain the structure of free list. * I was using union to hide the fact of overlapping memory * usage. However, that cause problem on MSVC. So, I now turn * back to hack this with casting. */ DateNode<T, ACE_LOCK> *next_; }; }; template <class T, class ACE_LOCK> class CachedAllocator : public ACE_New_Allocator { public: /// Create a cached memory pool with @a n_chunks chunks /// each with sizeof (TYPE) size. CachedAllocator(ManageAllocator<T, ACE_LOCK>* pParent, size_t n_chunks) : m_pParent(pParent) , pool_ (0), free_list_ (ACE_PURE_FREE_LIST) { // To maintain alignment requirements, make sure that each element // inserted into the free list is aligned properly for the platform. // Since the memory is allocated as a char[], the compiler won't help. // To make sure enough room is allocated, round up the size so that // each element starts aligned. // // NOTE - this would probably be easier by defining pool_ as a pointer // to T and allocating an array of them (the compiler would probably // take care of the alignment for us), but then the ACE_NEW below would // require a default constructor on T - a requirement that is not in // previous versions of ACE size_t chunk_size = sizeof (T); chunk_size = ACE_MALLOC_ROUNDUP (chunk_size, ACE_MALLOC_ALIGN); ACE_NEW (this->pool_, char[n_chunks * chunk_size]); for (size_t c = 0; c < n_chunks; c++) { void* placement = this->pool_ + c * chunk_size; this->free_list_.add (new (placement) ACE_Cached_Mem_Pool_Node<T>); } // Put into free list using placement contructor, no real memory // allocation in the above <new>. } /// Clear things up. ~ACE_Cached_Allocator (void) { delete [] this->pool_; } /** * Get a chunk of memory from free list cache. Note that @a nbytes is * only checked to make sure that it's less or equal to sizeof T, and is * otherwise ignored since @c malloc() always returns a pointer to an * item of sizeof (T). */ void *malloc (size_t nbytes = sizeof (T)) { // Check if size requested fits within pre-determined size. if (nbytes > sizeof (T)) return 0; // addr() call is really not absolutely necessary because of the way // ACE_Cached_Mem_Pool_Node's internal structure arranged. return this->free_list_.remove ()->addr (); } /** * Get a chunk of memory from free list cache, giving them * @a initial_value. Note that @a nbytes is only checked to make sure * that it's less or equal to sizeof T, and is otherwise ignored since * calloc() always returns a pointer to an item of sizeof (T). */ virtual void *calloc (size_t nbytes, char initial_value = '\0') { // Check if size requested fits within pre-determined size. if (nbytes > sizeof (T)) return 0; // addr() call is really not absolutely necessary because of the way // ACE_Cached_Mem_Pool_Node's internal structure arranged. void *ptr = this->free_list_.remove ()->addr (); if (ptr != 0) ACE_OS::memset (ptr, initial_value, sizeof (T)); return ptr; } /// This method is a no-op and just returns 0 since the free list /// only works with fixed sized entities. virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0') { ACE_NOTSUP_RETURN (0); } /// Return a chunk of memory back to free list cache. void free (void * ptr) { if (ptr != 0) this->free_list_.add ((ACE_Cached_Mem_Pool_Node<T> *) ptr) ; } /// Return the number of chunks available in the cache. size_t pool_depth (void) { return this->free_list_.size (); } private: ManageAllocator<T, ACE_LOCK>* m_pParent; /// Remember how we allocate the memory in the first place so /// we can clear things up later. char *pool_; /// Maintain a cached memory free list. ACE_Locked_Free_List<DateNode<T>, ACE_LOCK> free_list_; }; } #endif // #ifndef _H_hwnet_block_allocator_ #endif // HW_ACE HW_ACE_ALLOCATOR //使用自定义内存管理 经思考我写出了如上代码,后来一想,CachedAllocator 就是 ACE_Cached_Allocator,只不过节点类型变了,我何不直接使用ACE_Cached_Allocator,数据前面加一个ACE_Cached_Allocator父节点。还可以在改进,直接用ACE_Dynamic_Cached_Allocator。DateNode改为 #if (defined HW_ACE) && (defined HW_ACE_ALLOCATOR) // 使用自定义内存管理 #ifndef _H_hwnet_date_allocator_ #define _H_hwnet_date_allocator_ #include "ace/Malloc.h" #include <ace/Malloc_T.h> #include <boost/shared_ptr.hpp> namespace hwnet { template <class ACE_LOCK> class DateNode { public: DateNode<ACE_LOCK>(ACE_Allocator* pParent) : m_pParent(pParent) { assert(m_pParent); } ~DateNode<ACE_LOCK>() { assert(m_pParent); m_pParent->free(this); } static DateNode<ACE_LOCK>* GetDateNode(void* ptr) { if (ptr) { return (DateNode<ACE_LOCK>*)((char*)ptr + sizeof(DateNode<ACE_LOCK>)); } return NULL; } private: ACE_Allocator* m_pParent; }; template <class ACE_LOCK> class AllocatorNode : public ACE_New_Allocator { typedef ACE_Dynamic_Cached_Allocator<ACE_LOCK> ACEBlockAllocator; public: AllocatorNode(size_t MinBufSize // 最小数据内存 , size_t MaxBufSum // 一次申请个数 ) : m_MinBufSize(MinBufSize) // 最小数据内存 , m_MaxBufSum(MaxBufSum) // 一次申请个数 #ifdef _DEBUG , m_uSim(0) // 已经使用数量 #else #endif { } ~AllocatorNode() { for (std::deque<ACEBlockAllocator*>::iterator ite = m_deqAllocator.begin() ; ite != m_deqAllocator.end() ; ite++) { delete *ite; } } virtual void *malloc (size_t nbytes) { if (nbytes > m_MinBufSize) { return NULL; } ACE_GUARD_RETURN (ACE_LOCK, monitor, this->m_lock, NULL); #ifdef _DEBUG // 还有空闲 for (int i=m_deqAllocator.size()/2; i>=0; i--) #else #endif { for (std::deque<ACEBlockAllocator*>::iterator ite = m_deqAllocator.begin() ; ite != m_deqAllocator.end() ; ite++) { ACEBlockAllocator* pAllocator = *ite; if (pAllocator->pool_depth() > 0) { m_uSim++; void* ptr = pAllocator->malloc(nbytes); if (ptr) { #ifdef _DEBUG new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(this)); #else new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(pAllocator)); #endif } return (char*)ptr + sizeof(DateNode<ACE_LOCK>); } else { m_deqAllocator.pop_front(); m_deqAllocator.push_back(pAllocator); } } } // 重新分配 ACEBlockAllocator* pAllocator = new ACEBlockAllocator(m_MaxBufSum, m_MinBufSize + sizeof(ACE_New_Allocator*)); m_deqAllocator.push_front(pAllocator); void* ptr = pAllocator->malloc(nbytes); if (ptr) { m_uSim++; #ifdef _DEBUG new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(this)); #else new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(pAllocator)); #endif } return (char*)ptr + sizeof(DateNode<ACE_LOCK>); } virtual void *calloc (size_t nbytes, char initial_value = '\0') { void* ptr = malloc(nbytes); if (ptr) { ACE_OS::memset (ptr, initial_value, nbytes); } return ptr; } virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0') { return calloc (n_elem * elem_size, initial_value); } virtual void free (void* ptr) { #ifdef _DEBUG assert(m_uSim > 0); #else #endif //ACE_GUARD (ACE_LOCK, monitor, this->m_lock); if (ptr) { DateNode<ACE_LOCK>::GetDateNode(ptr)->~DateNode<ACE_LOCK>(); #ifdef _DEBUG m_uSim--; #else #endif } } private: ACE_LOCK m_lock; size_t m_MinBufSize; // 最小数据内存 size_t m_MaxBufSum; // 一次申请个数 std::deque<ACEBlockAllocator*> m_deqAllocator; #ifdef _DEBUG ACE_Atomic_Op<ACE_LOCK, size_t> m_uSim; // 已经使用数量 #else #endif }; } #endif // #ifndef _H_hwnet_date_allocator_ #endif // HW_ACE HW_ACE_ALLOCATOR //使用自定义内存管理 完整代码如下: /*************************************************************** version: 1.0 date: 16/5/2013 17:04 FileName: hwnet_block_allocator.h Author: 丁灵峰 Compiled on: VC.net 2008 ------------------------------------------------------------- Description: Modification history: Other: ------------------------------------------------------------- Copyright (C) 2010 - All Rights Reserved *************************************************************** ****************************************************************/ #if (defined HW_ACE) && (defined HW_ACE_ALLOCATOR) // 使用自定义内存管理 #ifndef _H_hwnet_date_allocator_ #define _H_hwnet_date_allocator_ #include "ace/Malloc.h" #include <ace/Malloc_T.h> #include <boost/shared_ptr.hpp> namespace hwnet { template <class ACE_LOCK> class ManageAllocator; template <class ACE_LOCK> class AllocatorNode; template <class ACE_LOCK> class DateNode { public: DateNode<ACE_LOCK>(ACE_Allocator* pParent) : m_pParent(pParent) { assert(m_pParent); } ~DateNode<ACE_LOCK>() { assert(m_pParent); m_pParent->free(this); } static DateNode<ACE_LOCK>* GetDateNode(void* ptr) { if (ptr) { return (DateNode<ACE_LOCK>*)((char*)ptr + sizeof(DateNode<ACE_LOCK>)); } return NULL; } private: ACE_Allocator* m_pParent; }; template <class ACE_LOCK> class AllocatorNode : public ACE_New_Allocator { typedef ACE_Dynamic_Cached_Allocator<ACE_LOCK> ACEBlockAllocator; public: AllocatorNode(size_t MinBufSize // 最小数据内存 , size_t MaxBufSum // 一次申请个数 ) : m_MinBufSize(MinBufSize) // 最小数据内存 , m_MaxBufSum(MaxBufSum) // 一次申请个数 #ifdef _DEBUG , m_uSim(0) // 已经使用数量 #else #endif { } ~AllocatorNode() { for (std::deque<ACEBlockAllocator*>::iterator ite = m_deqAllocator.begin() ; ite != m_deqAllocator.end() ; ite++) { delete *ite; } } virtual void *malloc (size_t nbytes) { if (nbytes > m_MinBufSize) { return NULL; } ACE_GUARD_RETURN (ACE_LOCK, monitor, this->m_lock, NULL); #ifdef _DEBUG // 还有空闲 for (int i=m_deqAllocator.size()/2; i>=0; i--) #else #endif { for (std::deque<ACEBlockAllocator*>::iterator ite = m_deqAllocator.begin() ; ite != m_deqAllocator.end() ; ite++) { ACEBlockAllocator* pAllocator = *ite; if (pAllocator->pool_depth() > 0) { m_uSim++; void* ptr = pAllocator->malloc(nbytes); if (ptr) { #ifdef _DEBUG new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(this)); #else new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(pAllocator)); #endif } return (char*)ptr + sizeof(DateNode<ACE_LOCK>); } else { m_deqAllocator.pop_front(); m_deqAllocator.push_back(pAllocator); } } } // 重新分配 ACEBlockAllocator* pAllocator = new ACEBlockAllocator(m_MaxBufSum, m_MinBufSize + sizeof(ACE_New_Allocator*)); m_deqAllocator.push_front(pAllocator); void* ptr = pAllocator->malloc(nbytes); if (ptr) { m_uSim++; #ifdef _DEBUG new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(this)); #else new (ptr) DateNode<ACE_LOCK>(dynamic_cast<ACE_Allocator*>(pAllocator)); #endif } return (char*)ptr + sizeof(DateNode<ACE_LOCK>); } virtual void *calloc (size_t nbytes, char initial_value = '\0') { void* ptr = malloc(nbytes); if (ptr) { ACE_OS::memset (ptr, initial_value, nbytes); } return ptr; } virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0') { return calloc (n_elem * elem_size, initial_value); } virtual void free (void* ptr) { #ifdef _DEBUG assert(m_uSim > 0); #else #endif //ACE_GUARD (ACE_LOCK, monitor, this->m_lock); if (ptr) { DateNode<ACE_LOCK>::GetDateNode(ptr)->~DateNode<ACE_LOCK>(); #ifdef _DEBUG m_uSim--; #else #endif } } private: ACE_LOCK m_lock; size_t m_MinBufSize; // 最小数据内存 size_t m_MaxBufSum; // 一次申请个数 std::deque<ACEBlockAllocator*> m_deqAllocator; #ifdef _DEBUG ACE_Atomic_Op<ACE_LOCK, size_t> m_uSim; // 已经使用数量 #else #endif }; template <class ACE_LOCK> class ManageAllocator : public ACE_New_Allocator //: public { // 友元 public: // 静态属性 // 静态函数 // 静态工具 // 接口实现 // 构造于析构 public: virtual ~ManageAllocator(void) { } ManageAllocator(std::set<size_t>& setMinSize // 最小数据内存,定长处理 , size_t MinBufSize // 最小数据内存,不定长用 , size_t MaxBufSum // 一次申请个数 ) // 不定长数据处理 #ifdef _DEBUG : m_uSim(0) // 已经使用数量 #else #endif { for (std::set<size_t>::iterator ite=setMinSize.begin() ; ite != setMinSize.end() ; ite++) { m_mapAllocatorNode[*ite] = boost::shared_ptr<AllocatorNode<ACE_LOCK> >(new AllocatorNode<ACE_LOCK>(*ite, MaxBufSum)); } } // 操作函数 public: virtual void *malloc (size_t nbytes) { ACE_GUARD_RETURN (ACE_LOCK, monitor, this->m_lock, NULL); // 分级 std::map<long, boost::shared_ptr<AllocatorNode<ACE_LOCK> > > m_mapAllocatorNode; for (std::map<long, boost::shared_ptr<AllocatorNode<ACE_LOCK> > >::iterator ite = m_mapAllocatorNode.begin() ; ite != m_mapAllocatorNode.end() ; ite++) { if (nbytes <= ite->first) { void* ptr = ite->second->malloc(nbytes); if (ptr) { #ifdef _DEBUG m_uSim++; #else #endif return ptr; } } } // 不定长数据处理 return NULL; } virtual void *calloc (size_t nbytes, char initial_value = '\0') { void* ptr = malloc(nbytes); if (ptr) { ACE_OS::memset (ptr, initial_value, nbytes); } return ptr; } virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0') { return calloc (n_elem * elem_size, initial_value); } virtual void free (void* ptr) { assert(m_uSim.value() > 0); ACE_GUARD (ACE_LOCK, monitor, this->m_lock); if (ptr) { DateNode<ACE_LOCK>::GetDateNode(ptr)->~DateNode<ACE_LOCK>(); #ifdef _DEBUG m_uSim--; #else #endif } } /// Return the number of chunks available in the cache. size_t Size (void) { return m_uSim.value(); } // 工具函数 private: protected: // 禁止 private: ManageAllocator(const ManageAllocator&); //复制构造 ManageAllocator & operator= (const ManageAllocator&); // 等于重载 // 属性 public: protected: ACE_LOCK m_lock; std::map<size_t, boost::shared_ptr<AllocatorNode<ACE_LOCK> > > m_mapAllocatorNode; #ifdef _DEBUG ACE_Atomic_Op<ACE_LOCK, size_t> m_uSim; // 已经使用数量 #else #endif }; } #endif // #ifndef _H_hwnet_date_allocator_ #endif // HW_ACE HW_ACE_ALLOCATOR //使用自定义内存管理 我们这样使用,注意,这个有效是哟前提假设的,条件更宽的情况请看下一篇. const static long S_BUFSIZ = 1024; // 一般申请大小,或者倍数 std::set<size_t> setMinSize; boost::shared_ptr<ManageAllocator<ACE_SYNCH_RECURSIVE_MUTEX> >gPManageBlockAllocator; setMinSize.insert(MAX(sizeof(ACE_Message_Block),sizeof(ACE_Data_Block))); setMinSize.insert(S_BUFSIZ); setMinSize.insert(S_BUFSIZ*3); gPManageBlockAllocator.reset(new ManageAllocator<ACE_SYNCH_RECURSIVE_MUTEX>(setMinSize, S_BUFSIZ, S_BUFSIZ*4)); ACE_Allocator::instance (dynamic_cast<ACE_Allocator*>(gPManageBlockAllocator.get()));
|
[挂载人]初学MPEG |
|
|
Please Login (or Sign Up) to leave a comment |