memory.cpp 3.3 KB

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