You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

134 lines
3.9 KiB

  1. #pragma once
  2. #include "arraylist.hpp"
  3. #include "types.hpp"
  4. template <typename type>
  5. struct Bucket_Allocator {
  6. u32 next_index_in_latest_bucket;
  7. u32 next_bucket_index;
  8. u32 bucket_count;
  9. u32 bucket_size;
  10. Array_List<type*> free_list;
  11. type** buckets;
  12. void clear() {
  13. next_index_in_latest_bucket = 0;
  14. next_bucket_index = 0;
  15. free_list.clear();
  16. }
  17. void expand() {
  18. buckets = (type**)ftb_realloc(buckets, bucket_count * 2 * sizeof(type*));
  19. bucket_count *= 2;
  20. }
  21. void jump_to_next_bucket() {
  22. next_index_in_latest_bucket = 0;
  23. ++next_bucket_index;
  24. if (next_bucket_index >= bucket_count) {
  25. expand();
  26. }
  27. buckets[next_bucket_index] = (type*)ftb_malloc(bucket_size * sizeof(type));
  28. }
  29. void increment_pointers(s32 amount = 1) {
  30. next_index_in_latest_bucket += amount;
  31. if (next_index_in_latest_bucket >= bucket_size) {
  32. jump_to_next_bucket();
  33. }
  34. }
  35. void alloc(u32 bucket_size = 16, u32 initial_bucket_count = 8) {
  36. this->free_list.alloc();
  37. this->bucket_size = bucket_size;
  38. next_index_in_latest_bucket = 0;
  39. next_bucket_index = 0;
  40. bucket_count = initial_bucket_count;
  41. buckets = (type**)ftb_malloc(bucket_count * sizeof(type*));
  42. buckets[0] = (type*)ftb_malloc(bucket_size * sizeof(type));
  43. }
  44. void dealloc() {
  45. for (u32 i = 0; i <= next_bucket_index; ++i) {
  46. ftb_free(buckets[i]);
  47. }
  48. this->free_list.dealloc();
  49. ftb_free(buckets);
  50. }
  51. u32 count_elements() {
  52. free_list.sort();
  53. type* val;
  54. u32 count = 0;
  55. for (u32 i = 0; i < next_bucket_index; ++i) {
  56. for (u32 j = 0; j < bucket_size; ++j) {
  57. val = buckets[i]+j;
  58. if (free_list.sorted_find(val) == -1)
  59. count++;
  60. }
  61. }
  62. for (u32 j = 0; j < next_index_in_latest_bucket; ++j) {
  63. val = buckets[next_bucket_index]+j;
  64. if (free_list.sorted_find(val) == -1)
  65. count++;
  66. }
  67. return count;
  68. }
  69. template <typename lambda>
  70. void for_each(lambda p) {
  71. free_list.sort();
  72. type* val;
  73. for (u32 i = 0; i < next_bucket_index; ++i) {
  74. for (u32 j = 0; j < bucket_size; ++j) {
  75. val = buckets[i]+j;
  76. if (free_list.sorted_find(val) == -1)
  77. p(val);
  78. }
  79. }
  80. for (u32 j = 0; j < next_index_in_latest_bucket; ++j) {
  81. val = buckets[next_bucket_index]+j;
  82. if (free_list.sorted_find(val) == -1)
  83. p(val);
  84. }
  85. }
  86. type* allocate(u32 amount = 1) {
  87. type* ret;
  88. if (amount == 0) return nullptr;
  89. if (amount == 1) {
  90. if (free_list.count != 0) {
  91. return free_list.data[--free_list.count];
  92. }
  93. ret = buckets[next_bucket_index]+next_index_in_latest_bucket;
  94. increment_pointers(1);
  95. return ret;
  96. }
  97. if (amount > bucket_size)
  98. return nullptr;
  99. if ((bucket_size - next_index_in_latest_bucket) >= 4) {
  100. // if the current bucket is ahs enough free space
  101. ret = buckets[next_bucket_index]+(next_index_in_latest_bucket);
  102. increment_pointers(amount);
  103. return ret;
  104. } else {
  105. // the current bucket does not have enough free space
  106. // add all remainding slots to free list
  107. while (next_index_in_latest_bucket < bucket_size) {
  108. free_list.append(buckets[next_bucket_index]+next_index_in_latest_bucket);
  109. ++next_index_in_latest_bucket;
  110. }
  111. jump_to_next_bucket();
  112. return allocate(amount);
  113. }
  114. }
  115. void free_object(type* obj) {
  116. free_list.append(obj);
  117. }
  118. };