Advertisement
Guest User

Untitled

a guest
Apr 21st, 2019
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.36 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include "rcu_lock.hpp"
  4. #include "spinlock.hpp"
  5.  
  6. #include <ctime>
  7. #include <twist/support/locking.hpp>
  8.  
  9. #include <functional>
  10. #include <vector>
  11.  
  12. namespace solutions {
  13.  
  14. template <typename Key, typename Value>
  15. class FixedSizeHashTable {
  16. private:
  17. class ListNode {
  18. public:
  19. ListNode(Key key, Value value, ListNode* next)
  20. : key_(key), value_(value), next_(next) {
  21. }
  22.  
  23. Key GetKey() {
  24. return key_;
  25. }
  26.  
  27. Value GetValue() {
  28. return value_;
  29. }
  30.  
  31. ListNode* GetNext() {
  32. return next_.load();
  33. }
  34.  
  35. void SetNext(ListNode* next) {
  36. next_.store(next);
  37. }
  38.  
  39. private:
  40. Key key_;
  41. Value value_;
  42. twist::atomic<ListNode*> next_;
  43. };
  44.  
  45. class Bucket {
  46. public:
  47. ListNode* GetHead() {
  48. return head_.load();
  49. }
  50.  
  51. void SetHead(ListNode* new_head) {
  52. head_.store(new_head);
  53. }
  54.  
  55. solutions::SpinLock* GetSpinLock() {
  56. return &spinlock_;
  57. }
  58.  
  59. solutions::RCULock* GetRCULock() {
  60. return &rculock_;
  61. }
  62.  
  63. private:
  64. solutions::RCULock rculock_;
  65. solutions::SpinLock spinlock_;
  66. twist::atomic<ListNode*> head_{nullptr};
  67. };
  68.  
  69. public:
  70. FixedSizeHashTable(size_t num_buckets) : buckets_(num_buckets) {
  71. }
  72.  
  73. bool Insert(const Key& key, const Value& value) {
  74. auto bucket = GetBucket(key);
  75. solutions::SpinLock* spinlock = bucket->GetSpinLock();
  76. auto lock = twist::LockUnique<solutions::SpinLock>(*spinlock);
  77.  
  78. auto curr = bucket->GetHead();
  79. while (curr != nullptr) {
  80. if (curr->GetKey() == key) {
  81. return false;
  82. }
  83. curr = curr->GetNext();
  84. }
  85.  
  86. auto new_node = new ListNode(key, value, bucket->GetHead());
  87. bucket->SetHead(new_node);
  88. return true;
  89. }
  90.  
  91. bool Remove(const Key& key) {
  92. auto bucket = GetBucket(key);
  93. solutions::SpinLock* spinlock = bucket->GetSpinLock();
  94. auto lock = twist::LockUnique<solutions::SpinLock>(*spinlock);
  95.  
  96. ListNode* curr = nullptr;
  97. ListNode* next = bucket->GetHead();
  98.  
  99. if (next == nullptr) {
  100. return false;
  101. }
  102.  
  103. if (next != nullptr && next->GetKey() == key) {
  104. bucket->SetHead(next->GetNext());
  105. solutions::RCULock* rculock = bucket->GetRCULock();
  106. rculock->Synchronize();
  107. delete (ListNode*)next;
  108. return true;
  109. }
  110.  
  111. curr = next;
  112. next = curr->GetNext();
  113. while (next != nullptr) {
  114. if (next->GetKey() == key) {
  115. curr->SetNext(next->GetNext());
  116. solutions::RCULock* rculock = bucket->GetRCULock();
  117. rculock->Synchronize();
  118. delete (ListNode*)next;
  119. return true;
  120. }
  121. curr = next;
  122. next = curr->GetNext();
  123. }
  124.  
  125. return false;
  126. }
  127.  
  128. // Wait-free
  129. bool Lookup(const Key& key, Value& value) {
  130. Bucket* bucket = GetBucket(key);
  131. solutions::RCULock* rculock = bucket->GetRCULock();
  132. auto lock = twist::LockShared<solutions::RCULock>(*rculock);
  133.  
  134. auto curr = bucket->GetHead();
  135. while (curr != nullptr) {
  136. if (curr->GetKey() == key) {
  137. value = curr->GetValue();
  138. return true;
  139. }
  140. curr = curr->GetNext();
  141. }
  142. return false;
  143. }
  144.  
  145. private:
  146. Bucket* GetBucket(const Key& key) {
  147. return &buckets_[std::hash<Key>()(key) % buckets_.size()];
  148. }
  149.  
  150. private:
  151. std::vector<Bucket> buckets_;
  152. };
  153.  
  154. } // namespace solutions
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement