memory.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "memory.h"
  6. #include "allocator.h"
  7. #include "mutex.h"
  8. // void* operator new(size_t) throw (std::bad_alloc)
  9. // {
  10. // CE_ASSERT(false, "operator new forbidden");
  11. // return NULL;
  12. // }
  13. // void* operator new[](size_t) throw (std::bad_alloc)
  14. // {
  15. // CE_ASSERT(false, "operator new[] forbidden");
  16. // return NULL;
  17. // }
  18. // void operator delete(void*) throw ()
  19. // {
  20. // CE_ASSERT(false, "operator delete forbidden");
  21. // }
  22. // void operator delete[](void*) throw ()
  23. // {
  24. // CE_ASSERT(false, "operator delete[] forbidden");
  25. // }
  26. namespace crown
  27. {
  28. namespace memory
  29. {
  30. /// Allocator based on C malloc().
  31. class HeapAllocator : public Allocator
  32. {
  33. public:
  34. HeapAllocator()
  35. : _allocated_size(0)
  36. , _allocation_count(0)
  37. {
  38. }
  39. ~HeapAllocator()
  40. {
  41. CE_ASSERT(_allocation_count == 0 && total_allocated() == 0,
  42. "Missing %d deallocations causing a leak of %ld bytes", _allocation_count, total_allocated());
  43. }
  44. /// @copydoc Allocator::allocate()
  45. void* allocate(size_t size, size_t align = Allocator::DEFAULT_ALIGN)
  46. {
  47. ScopedMutex sm(_mutex);
  48. size_t actual_size = actual_allocation_size(size, align);
  49. Header* h = (Header*)malloc(actual_size);
  50. h->size = actual_size;
  51. void* data = memory::align_top(h + 1, align);
  52. pad(h, data);
  53. _allocated_size += actual_size;
  54. _allocation_count++;
  55. return data;
  56. }
  57. /// @copydoc Allocator::deallocate()
  58. void deallocate(void* data)
  59. {
  60. ScopedMutex sm(_mutex);
  61. if (!data)
  62. return;
  63. Header* h = header(data);
  64. _allocated_size -= h->size;
  65. _allocation_count--;
  66. free(h);
  67. }
  68. /// @copydoc Allocator::allocated_size()
  69. uint32_t allocated_size(const void* ptr)
  70. {
  71. return get_size(ptr);
  72. }
  73. /// @copydoc Allocator::total_allocated()
  74. uint32_t total_allocated()
  75. {
  76. ScopedMutex sm(_mutex);
  77. return _allocated_size;
  78. }
  79. /// Returns the size in bytes of the block of memory pointed by @a data
  80. size_t get_size(const void* data)
  81. {
  82. ScopedMutex sm(_mutex);
  83. Header* h = header(data);
  84. return h->size;
  85. }
  86. private:
  87. // Holds the number of bytes of an allocation
  88. struct Header
  89. {
  90. uint32_t size;
  91. };
  92. size_t actual_allocation_size(size_t size, size_t align)
  93. {
  94. return size + align + sizeof(Header);
  95. }
  96. Header* header(const void* data)
  97. {
  98. const uint32_t* ptr = (uint32_t*)data;
  99. ptr--;
  100. while (*ptr == memory::PADDING_VALUE)
  101. {
  102. ptr--;
  103. }
  104. return (Header*)ptr;
  105. }
  106. void* data(Header* header, size_t align)
  107. {
  108. return memory::align_top(header + 1, align);
  109. }
  110. void pad(Header* header, void* data)
  111. {
  112. uint32_t* p = (uint32_t*)(header + 1);
  113. while (p != data)
  114. {
  115. *p = memory::PADDING_VALUE;
  116. p++;
  117. }
  118. }
  119. private:
  120. Mutex _mutex;
  121. size_t _allocated_size;
  122. uint32_t _allocation_count;
  123. };
  124. } // namespace memory
  125. namespace memory_globals
  126. {
  127. using namespace memory;
  128. // Create default allocators
  129. char _buffer[1024];
  130. HeapAllocator* _default_allocator = NULL;
  131. void init()
  132. {
  133. _default_allocator = new (_buffer) HeapAllocator();
  134. }
  135. void shutdown()
  136. {
  137. _default_allocator->~HeapAllocator();
  138. }
  139. } // namespace memory_globals
  140. Allocator& default_allocator()
  141. {
  142. return *memory_globals::_default_allocator;
  143. }
  144. } // namespace crown