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.
 
 
 
 

127 rivejä
3.7 KiB

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