allocator.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #pragma once
  2. #include <kernel/mem.h>
  3. #include <types/cplusplus.hpp>
  4. #include <types/stdint.h>
  5. #include <types/types.h>
  6. inline void* operator new(size_t, void* ptr)
  7. {
  8. return ptr;
  9. }
  10. namespace types {
  11. template <typename T>
  12. concept Allocator = requires(size_t size, typename T::value_type* ptr)
  13. {
  14. typename T::value_type;
  15. {
  16. T::allocate_memory(size)
  17. } -> same_as<typename T::value_type*>;
  18. {
  19. T::deallocate_memory(ptr)
  20. } -> same_as<void>;
  21. };
  22. template <Allocator T>
  23. class allocator_traits;
  24. template <typename T>
  25. class kernel_allocator {
  26. public:
  27. using value_type = T;
  28. static value_type* allocate_memory(size_t count)
  29. {
  30. return static_cast<value_type*>(::k_malloc(count));
  31. }
  32. static void deallocate_memory(value_type* ptr)
  33. {
  34. ::k_free(ptr);
  35. }
  36. };
  37. template <typename T>
  38. class kernel_ident_allocator {
  39. public:
  40. using value_type = T;
  41. static value_type* allocate_memory(size_t count)
  42. {
  43. return static_cast<value_type*>(::ki_malloc(count));
  44. }
  45. static void deallocate_memory(value_type* ptr)
  46. {
  47. ::ki_free(ptr);
  48. }
  49. };
  50. template <typename T, typename... Args>
  51. constexpr T* kernel_allocator_new(Args&&... args)
  52. {
  53. return allocator_traits<kernel_allocator<T>>::allocate_and_construct(forward<Args>(args)...);
  54. }
  55. template <PointerType T, typename... Args>
  56. constexpr auto kernel_allocator_pnew(T, Args&&... args)
  57. {
  58. using value_type = typename traits::remove_pointer<T>::type;
  59. return kernel_allocator_new<value_type>(forward<Args>(args)...);
  60. }
  61. template <typename T, typename... Args>
  62. constexpr T* kernel_ident_allocator_new(Args&&... args)
  63. {
  64. return allocator_traits<kernel_ident_allocator<T>>::allocate_and_construct(forward<Args>(args)...);
  65. }
  66. template <PointerType T, typename... Args>
  67. constexpr auto kernel_ident_allocator_pnew(T, Args&&... args)
  68. {
  69. using value_type = typename traits::remove_pointer<T>::type;
  70. return kernel_ident_allocator_new<value_type>(forward<Args>(args)...);
  71. }
  72. template <PointerType T>
  73. constexpr void kernel_allocator_delete(T ptr)
  74. {
  75. using value_type = typename traits::remove_pointer<T>::type;
  76. return allocator_traits<kernel_allocator<value_type>>::deconstruct_and_deallocate(ptr);
  77. }
  78. template <PointerType T>
  79. constexpr void kernel_ident_allocator_delete(T ptr)
  80. {
  81. using value_type = typename traits::remove_pointer<T>::type;
  82. return allocator_traits<kernel_ident_allocator<value_type>>::deconstruct_and_deallocate(ptr);
  83. }
  84. template <Allocator _allocator>
  85. class allocator_traits {
  86. public:
  87. using value_type = typename _allocator::value_type;
  88. static value_type* allocate(size_t count)
  89. {
  90. if (count == 0)
  91. return nullptr;
  92. return _allocator::allocate_memory(sizeof(value_type) * count);
  93. }
  94. template <typename... Args>
  95. static value_type* construct(value_type* ptr, Args&&... args)
  96. {
  97. new (ptr) value_type(forward<Args>(args)...);
  98. return ptr;
  99. }
  100. template <typename... Args>
  101. static value_type* allocate_and_construct(Args&&... args)
  102. {
  103. auto* ptr = allocate(1);
  104. construct(ptr, forward<Args>(args)...);
  105. return ptr;
  106. }
  107. static void deconstruct(value_type* ptr)
  108. {
  109. if (!ptr)
  110. return;
  111. ptr->~value_type();
  112. }
  113. static void deallocate(value_type* ptr)
  114. {
  115. if (!ptr)
  116. return;
  117. _allocator::deallocate_memory(ptr);
  118. }
  119. static void deconstruct_and_deallocate(value_type* ptr)
  120. {
  121. if (!ptr)
  122. return;
  123. deconstruct(ptr);
  124. deallocate(ptr);
  125. }
  126. };
  127. } // namespace types