mem_mgr.txx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**
  2. * \file mem_mgr.txx
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 9-21-2014
  5. * \brief This file contains the definition of a simple memory manager which
  6. * uses a pre-allocated buffer of size defined in call to the constructor.
  7. */
  8. #include <omp.h>
  9. #include <algorithm>
  10. #include <cstring>
  11. #include <cassert>
  12. #include <device_wrapper.hpp>
  13. namespace pvfmm{
  14. namespace mem{
  15. template <class T>
  16. uintptr_t TypeTraits<T>::ID(){
  17. return (uintptr_t)&ID;
  18. }
  19. template <class T>
  20. bool TypeTraits<T>::IsPOD(){
  21. return false;
  22. }
  23. #define PVFMMDefinePOD(type) template<> bool inline TypeTraits<type>::IsPOD(){return true;};
  24. PVFMMDefinePOD(char);
  25. PVFMMDefinePOD(float);
  26. PVFMMDefinePOD(double);
  27. PVFMMDefinePOD(int);
  28. PVFMMDefinePOD(long long);
  29. PVFMMDefinePOD(unsigned long);
  30. PVFMMDefinePOD(char*);
  31. PVFMMDefinePOD(float*);
  32. PVFMMDefinePOD(double*);
  33. #undef PVFMMDefinePOD
  34. MemoryManager::MemHead* MemoryManager::GetMemHead(void* p){
  35. static uintptr_t alignment=MEM_ALIGN-1;
  36. static uintptr_t header_size=(uintptr_t)(sizeof(MemoryManager::MemHead)+alignment) & ~(uintptr_t)alignment;
  37. return (MemHead*)(((char*)p)-header_size);
  38. }
  39. size_t MemoryManager::new_node() const{
  40. if(node_stack.empty()){
  41. node_buff.resize(node_buff.size()+1);
  42. node_stack.push(node_buff.size());
  43. }
  44. size_t indx=node_stack.top();
  45. node_stack.pop();
  46. assert(indx);
  47. return indx;
  48. }
  49. void MemoryManager::delete_node(size_t indx) const{
  50. assert(indx);
  51. assert(indx<=node_buff.size());
  52. MemNode& n=node_buff[indx-1];
  53. n.free=false;
  54. n.size=0;
  55. n.prev=0;
  56. n.next=0;
  57. n.mem_ptr=NULL;
  58. node_stack.push(indx);
  59. }
  60. template <class T>
  61. T* aligned_new(size_t n_elem, const MemoryManager* mem_mgr){
  62. if(!n_elem) return NULL;
  63. static MemoryManager def_mem_mgr(0);
  64. if(!mem_mgr) mem_mgr=&def_mem_mgr;
  65. T* A=(T*)mem_mgr->malloc(n_elem, sizeof(T));
  66. if(!TypeTraits<T>::IsPOD()){ // Call constructors
  67. //printf("%s\n", __PRETTY_FUNCTION__);
  68. #pragma omp parallel for
  69. for(size_t i=0;i<n_elem;i++){
  70. T* Ai=new(A+i) T();
  71. assert(Ai==(A+i));
  72. }
  73. }else{
  74. #ifndef NDEBUG
  75. #pragma omp parallel for
  76. for(size_t i=0;i<n_elem*sizeof(T);i++){
  77. ((char*)A)[i]=0;
  78. }
  79. #endif
  80. }
  81. assert(A);
  82. return A;
  83. }
  84. template <class T>
  85. void aligned_delete(T* A, const MemoryManager* mem_mgr){
  86. if (!A) return;
  87. if(!TypeTraits<T>::IsPOD()){ // Call destructors
  88. //printf("%s\n", __PRETTY_FUNCTION__);
  89. MemoryManager::MemHead* mem_head=MemoryManager::GetMemHead(A);
  90. size_t type_size=mem_head->type_size;
  91. size_t n_elem=mem_head->n_elem;
  92. for(size_t i=0;i<n_elem;i++){
  93. ((T*)(((char*)A)+i*type_size))->~T();
  94. }
  95. }else{
  96. #ifndef NDEBUG
  97. MemoryManager::MemHead* mem_head=MemoryManager::GetMemHead(A);
  98. size_t type_size=mem_head->type_size;
  99. size_t n_elem=mem_head->n_elem;
  100. size_t size=n_elem*type_size;
  101. #pragma omp parallel for
  102. for(size_t i=0;i<size;i++){
  103. ((char*)A)[i]=0;
  104. }
  105. #endif
  106. }
  107. static MemoryManager def_mem_mgr(0);
  108. if(!mem_mgr) mem_mgr=&def_mem_mgr;
  109. mem_mgr->free(A);
  110. }
  111. void* memcopy( void * destination, const void * source, size_t num){
  112. if(destination==source || num==0) return destination;
  113. return memcpy ( destination, source, num );
  114. }
  115. }//end namespace
  116. }//end namespace