Guest User

Untitled

a guest
Apr 23rd, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.11 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include "rcu_lock.hpp"
  4. #include "spinlock.hpp"
  5.  
  6. #include <twist/support/locking.hpp>
  7.  
  8. #include <functional>
  9. #include <vector>
  10. #include <iostream>
  11.  
  12. namespace solutions {
  13.  
  14. template <typename Key, typename Value>
  15. class FixedSizeHashTable {
  16. private:
  17. class Bucket {
  18. public:
  19. struct Node {
  20. Node(const Key& key_val, const Value& val)
  21. : key(key_val), value(val), next(nullptr) {
  22. }
  23.  
  24. twist::atomic<Node*> next;
  25. const Value value;
  26. const Key key;
  27. };
  28.  
  29. bool Insert(const Key& key, const Value& value) {
  30. auto lock = twist::LockUnique(write_lock_);
  31. Node* new_node = new Node(key, value);
  32. if (head_.load() == nullptr) {
  33. head_.store(new_node);
  34. return true;
  35. } else {
  36. Node* temp = head_.load();
  37. while (temp->next.load() != nullptr) {
  38. if (temp->key == key) {
  39. delete new_node;
  40. return false;
  41. }
  42. temp = temp->next.load();
  43. }
  44. if (temp->key == key) {
  45. delete new_node;
  46. return false;
  47. }
  48. temp->next.store(new_node);
  49. return true;
  50. }
  51. }
  52.  
  53. bool Remove(const Key& key) {
  54. auto lock = twist::LockUnique(write_lock_);
  55. if (head_.load() == nullptr) {
  56. return false;
  57. }
  58. if (head_.load()->key == key) {
  59. Node* head = head_.load();
  60. Node* head_next = head->next.load();
  61. head_.store(head_next);
  62. read_lock_.Synchronize();
  63. delete head;
  64. return true;
  65. } else {
  66. Node* temp = head_.load();
  67. while (temp->next.load() != nullptr) {
  68. if (temp->next.load()->key == key) {
  69. Node* next = temp->next.load();
  70. Node* new_next = next->next.load();
  71. temp->next.store(new_next);
  72. read_lock_.Synchronize();
  73. delete next;
  74. return true;
  75. }
  76. temp = temp->next.load();
  77. }
  78. return false;
  79. }
  80. }
  81.  
  82. bool Lookup(const Key& key, Value& value) {
  83. auto lock = twist::LockShared(read_lock_);
  84. Node* temp = head_.load();
  85. while (temp != nullptr) {
  86. if (temp->key == key) {
  87. value = temp->value;
  88. return true;
  89. }
  90. temp = temp->next.load();
  91. }
  92. return false;
  93. }
  94.  
  95. private:
  96. SpinLock write_lock_;
  97. RCULock read_lock_;
  98. twist::atomic<Node*> head_{nullptr};
  99. };
  100.  
  101. public:
  102. FixedSizeHashTable(size_t num_buckets) : buckets_(num_buckets) {
  103. }
  104.  
  105. bool Insert(const Key& key, const Value& value) {
  106. size_t index = (std::hash<Key>{}(key)) % buckets_.size();
  107. return buckets_[index].Insert(key, value);
  108. }
  109.  
  110. bool Remove(const Key& key) {
  111. size_t index = (std::hash<Key>{}(key)) % buckets_.size();
  112. return buckets_[index].Remove(key);
  113. }
  114.  
  115. // Wait-free
  116. bool Lookup(const Key& key, Value& value) {
  117. size_t index = (std::hash<Key>{}(key)) % buckets_.size();
  118. return buckets_[index].Lookup(key, value);
  119. }
  120.  
  121. private:
  122. std::vector<Bucket> buckets_;
  123. };
  124.  
  125. } // namespace solutions
Advertisement
Add Comment
Please, Sign In to add comment