/** * \file mem_mgr.hpp * \author Dhairya Malhotra, dhairya.malhotra@gmail.com * \date 6-30-2014 * \brief This file contains the definition of a simple memory manager which * uses a pre-allocated buffer of size defined in call to the constructor. */ #include #include #include #include #include #include #include #include #include #include #ifndef _PVFMM_MEM_MGR_HPP_ #define _PVFMM_MEM_MGR_HPP_ #ifdef __INTEL_OFFLOAD #pragma offload_attribute(push,target(mic)) #endif namespace pvfmm{ namespace mem{ class MemoryManager{ public: static const char init_mem_val=42; MemoryManager(size_t N){ buff_size=N; buff=(char*)::malloc(buff_size); assert(buff); { // Debugging #ifndef NDEBUG for(size_t i=0;inext-1]; if(n==NULL || !n->free || n->size!=buff_size || node_stack.size()!=node_buff.size()-2){ std::cout<<"\nWarning: memory leak detected.\n"; } omp_destroy_lock(&omp_lock); { // Debugging #ifndef NDEBUG for(size_t i=0;i::iterator it; uintptr_t r=0; omp_set_lock(&omp_lock); it=free_map.lower_bound(size); if(it==free_map.end()){ // Use system malloc r = (uintptr_t)::malloc(size); }else if(it->first==size){ // Found exact size block size_t n_indx=it->second; node& n=node_buff[n_indx-1]; assert(n.size==it->first); assert(n.it==it); assert(n.free); n.free=false; { // Debugging #ifndef NDEBUG for(size_t i=0;isecond; size_t n_free_indx=new_node(); node& n_free=node_buff[n_free_indx-1]; node& n =node_buff[n_indx-1]; assert(n.size==it->first); assert(n.it==it); assert(n.free); n_free=n; n_free.size-=size; n_free.mem_ptr=(char*)n_free.mem_ptr+size; n_free.prev=n_indx; if(n_free.next){ size_t n_next_indx=n_free.next; node& n_next=node_buff[n_next_indx-1]; n_next.prev=n_free_indx; } n.free=false; n.size=size; n.next=n_free_indx; { // Debugging #ifndef NDEBUG for(size_t i=0;i=&buff[buff_size]) return ::free(p); size_t n_indx=((size_t*)p)[-1]; assert(n_indx>0 && n_indx<=node_buff.size()); omp_set_lock(&omp_lock); node& n=node_buff[n_indx-1]; assert(!n.free && n.size>0 && n.mem_ptr==&((size_t*)p)[-1]); { // Debugging #ifndef NDEBUG for(char* c=((char*)p )-sizeof( size_t);c<((char*)p );c++) *c=init_mem_val; for(char* c=((char*)p_)-sizeof(uint16_t);c<((char*)p_);c++) *c=init_mem_val; //((size_t*)p)[-1]=0; //((uint16_t*)p_)[-1]=0; size_t alignment=MEM_ALIGN; size_t size=n.size-(sizeof(size_t) + --alignment + 2); for(size_t i=0;inext){ n=&node_buff[n->next-1]; if(n->free){ std::cout<<' '; largest_size=std::max(largest_size,n->size); } else{ std::cout<<'#'; size+=n->size; } } std::cout<<"| allocated="<::iterator it; }; MemoryManager(); MemoryManager(const MemoryManager& m); size_t new_node() const{ if(node_stack.empty()){ node_buff.resize(node_buff.size()+1); node_stack.push(node_buff.size()); } size_t indx=node_stack.top(); node_stack.pop(); assert(indx); return indx; } void delete_node(size_t indx) const{ assert(indx); assert(indx<=node_buff.size()); node& n=node_buff[indx-1]; n.size=0; n.prev=0; n.next=0; n.mem_ptr=NULL; node_stack.push(indx); } char* buff; size_t buff_size; size_t n_dummy_indx; mutable std::vector node_buff; mutable std::stack node_stack; mutable std::multimap free_map; mutable omp_lock_t omp_lock; }; const MemoryManager glbMemMgr(GLOBAL_MEM_BUFF*1024LL*1024LL); }//end namespace }//end namespace #ifdef __INTEL_OFFLOAD #pragma offload_attribute(pop) #endif #endif //_PVFMM_MEM_MGR_HPP_