dict.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #pragma once
  2. #include "obj.h"
  3. #include "common.h"
  4. #include "memory.h"
  5. #include "str.h"
  6. namespace pkpy{
  7. struct Dict{
  8. using Item = std::pair<PyObject*, PyObject*>;
  9. static constexpr int __Capacity = 8;
  10. static constexpr float __LoadFactor = 0.67f;
  11. static_assert(sizeof(Item) * __Capacity <= 128);
  12. VM* vm;
  13. int _capacity;
  14. int _mask;
  15. int _size;
  16. int _critical_size;
  17. Item* _items;
  18. Dict(VM* vm): vm(vm), _capacity(__Capacity),
  19. _mask(__Capacity-1),
  20. _size(0), _critical_size(__Capacity*__LoadFactor+0.5f){
  21. _items = (Item*)pool128.alloc(_capacity * sizeof(Item));
  22. memset(_items, 0, _capacity * sizeof(Item));
  23. }
  24. int size() const { return _size; }
  25. Dict(Dict&& other){
  26. vm = other.vm;
  27. _capacity = other._capacity;
  28. _mask = other._mask;
  29. _size = other._size;
  30. _critical_size = other._critical_size;
  31. _items = other._items;
  32. other._items = nullptr;
  33. }
  34. Dict(const Dict& other){
  35. vm = other.vm;
  36. _capacity = other._capacity;
  37. _mask = other._mask;
  38. _size = other._size;
  39. _critical_size = other._critical_size;
  40. _items = (Item*)pool128.alloc(_capacity * sizeof(Item));
  41. memcpy(_items, other._items, _capacity * sizeof(Item));
  42. }
  43. Dict& operator=(const Dict&) = delete;
  44. Dict& operator=(Dict&&) = delete;
  45. void _probe(PyObject* key, bool& ok, int& i) const;
  46. void set(PyObject* key, PyObject* val){
  47. bool ok; int i;
  48. _probe(key, ok, i);
  49. if(!ok) {
  50. _size++;
  51. if(_size > _critical_size){
  52. _rehash();
  53. _probe(key, ok, i);
  54. }
  55. _items[i].first = key;
  56. }
  57. _items[i].second = val;
  58. }
  59. void _rehash(){
  60. Item* old_items = _items;
  61. int old_capacity = _capacity;
  62. _capacity *= 2;
  63. _mask = _capacity - 1;
  64. _critical_size = _capacity * __LoadFactor + 0.5f;
  65. _items = (Item*)pool128.alloc(_capacity * sizeof(Item));
  66. memset(_items, 0, _capacity * sizeof(Item));
  67. for(int i=0; i<old_capacity; i++){
  68. if(old_items[i].first == nullptr) continue;
  69. bool ok; int j;
  70. _probe(old_items[i].first, ok, j);
  71. if(ok) FATAL_ERROR();
  72. _items[j] = old_items[i];
  73. }
  74. pool128.dealloc(old_items);
  75. }
  76. PyObject* try_get(PyObject* key) const{
  77. bool ok; int i;
  78. _probe(key, ok, i);
  79. if(!ok) return nullptr;
  80. return _items[i].second;
  81. }
  82. bool contains(PyObject* key) const{
  83. bool ok; int i;
  84. _probe(key, ok, i);
  85. return ok;
  86. }
  87. void erase(PyObject* key){
  88. bool ok; int i;
  89. _probe(key, ok, i);
  90. if(!ok) return;
  91. _items[i].first = nullptr;
  92. _items[i].second = nullptr;
  93. _size--;
  94. }
  95. void update(const Dict& other){
  96. for(int i=0; i<other._capacity; i++){
  97. if(other._items[i].first == nullptr) continue;
  98. set(other._items[i].first, other._items[i].second);
  99. }
  100. }
  101. std::vector<Item> items() const {
  102. std::vector<Item> v;
  103. for(int i=0; i<_capacity; i++){
  104. if(_items[i].first == nullptr) continue;
  105. v.push_back(_items[i]);
  106. }
  107. return v;
  108. }
  109. template<typename __Func>
  110. void apply(__Func f) const {
  111. for(int i=0; i<_capacity; i++){
  112. if(_items[i].first == nullptr) continue;
  113. f(_items[i].first, _items[i].second);
  114. }
  115. }
  116. void clear(){
  117. memset(_items, 0, _capacity * sizeof(Item));
  118. _size = 0;
  119. }
  120. ~Dict(){ if(_items!=nullptr) pool128.dealloc(_items); }
  121. void _gc_mark() const{
  122. for(int i=0; i<_capacity; i++){
  123. if(_items[i].first == nullptr) continue;
  124. PK_OBJ_MARK(_items[i].first);
  125. PK_OBJ_MARK(_items[i].second);
  126. }
  127. }
  128. };
  129. } // namespace pkpy