123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- /**
- * \file mem_mgr.txx
- * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
- * \date 9-21-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 <omp.h>
- #include <algorithm>
- #include <cstring>
- #include <cassert>
- #include <device_wrapper.hpp>
- namespace pvfmm{
- namespace mem{
- template <class T>
- uintptr_t TypeTraits<T>::ID(){
- return (uintptr_t)&ID;
- }
- template <class T>
- bool TypeTraits<T>::IsPOD(){
- return false;
- }
- #define PVFMMDefinePOD(type) template<> bool inline TypeTraits<type>::IsPOD(){return true;};
- PVFMMDefinePOD(char);
- PVFMMDefinePOD(float);
- PVFMMDefinePOD(double);
- PVFMMDefinePOD(int);
- PVFMMDefinePOD(long long);
- PVFMMDefinePOD(unsigned long);
- PVFMMDefinePOD(char*);
- PVFMMDefinePOD(float*);
- PVFMMDefinePOD(double*);
- #undef PVFMMDefinePOD
- MemoryManager::MemHead* MemoryManager::GetMemHead(void* p){
- static uintptr_t alignment=MEM_ALIGN-1;
- static uintptr_t header_size=(uintptr_t)(sizeof(MemoryManager::MemHead)+alignment) & ~(uintptr_t)alignment;
- return (MemHead*)(((char*)p)-header_size);
- }
- size_t MemoryManager::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 MemoryManager::delete_node(size_t indx) const{
- assert(indx);
- assert(indx<=node_buff.size());
- MemNode& n=node_buff[indx-1];
- n.free=false;
- n.size=0;
- n.prev=0;
- n.next=0;
- n.mem_ptr=NULL;
- node_stack.push(indx);
- }
- template <class T>
- T* aligned_new(size_t n_elem, const MemoryManager* mem_mgr){
- if(!n_elem) return NULL;
- static MemoryManager def_mem_mgr(0);
- if(!mem_mgr) mem_mgr=&def_mem_mgr;
- T* A=(T*)mem_mgr->malloc(n_elem, sizeof(T));
- if(!TypeTraits<T>::IsPOD()){ // Call constructors
- //printf("%s\n", __PRETTY_FUNCTION__);
- #pragma omp parallel for
- for(size_t i=0;i<n_elem;i++){
- T* Ai=new(A+i) T();
- assert(Ai==(A+i));
- }
- }else{
- #ifndef NDEBUG
- #pragma omp parallel for
- for(size_t i=0;i<n_elem*sizeof(T);i++){
- ((char*)A)[i]=0;
- }
- #endif
- }
- assert(A);
- return A;
- }
- template <class T>
- void aligned_delete(T* A, const MemoryManager* mem_mgr){
- if (!A) return;
- if(!TypeTraits<T>::IsPOD()){ // Call destructors
- //printf("%s\n", __PRETTY_FUNCTION__);
- MemoryManager::MemHead* mem_head=MemoryManager::GetMemHead(A);
- size_t type_size=mem_head->type_size;
- size_t n_elem=mem_head->n_elem;
- for(size_t i=0;i<n_elem;i++){
- ((T*)(((char*)A)+i*type_size))->~T();
- }
- }else{
- #ifndef NDEBUG
- MemoryManager::MemHead* mem_head=MemoryManager::GetMemHead(A);
- size_t type_size=mem_head->type_size;
- size_t n_elem=mem_head->n_elem;
- size_t size=n_elem*type_size;
- #pragma omp parallel for
- for(size_t i=0;i<size;i++){
- ((char*)A)[i]=0;
- }
- #endif
- }
- static MemoryManager def_mem_mgr(0);
- if(!mem_mgr) mem_mgr=&def_mem_mgr;
- mem_mgr->free(A);
- }
- void* memcopy( void * destination, const void * source, size_t num){
- if(destination==source || num==0) return destination;
- return memcpy ( destination, source, num );
- }
- }//end namespace
- }//end namespace
|