Advertisement
Guest User

Untitled

a guest
Nov 30th, 2015
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.71 KB | None | 0 0
  1. #ifndef _atomichashset_hpp
  2. #define _atomichashset_hpp
  3.  
  4. #include <stddef.h>
  5. #include <atomic>
  6. #include <functional>
  7.  
  8. template <typename T>
  9. class AtomicHashSet
  10. {
  11. private:
  12.     /*
  13.      * the reserved state is added to reserve a position, before
  14.      * storing the pointer to the given key. after storing is
  15.      * completed the state should be set to occupied.
  16.      */
  17.     enum class State {
  18.         Empty, Occupied, Deleted
  19.     };
  20.  
  21.     typedef struct entry {
  22.         State state;
  23.         const T* element;
  24.     } entry_t ;
  25.  
  26.     static const size_t max_size = 128;
  27.     std::atomic<entry_t> elements[max_size];
  28.     std::atomic<size_t> size_counter;
  29.  
  30. private:
  31.     size_t bound(size_t pos) const {
  32.         return pos % max_size;
  33.     }
  34.  
  35.     size_t getHash(const T&key) const {
  36.         return bound(std::hash<const T*>()(&key));
  37.     }
  38.  
  39.     bool isEmpty(entry_t& entry) const {
  40.         return entry.state == State::Empty;
  41.     }
  42.  
  43.     bool isFree(entry_t& entry) const {
  44.         State state = entry.state;
  45.         return state == State::Empty || state == State::Deleted;
  46.     }
  47.  
  48.     bool isOccupied(entry_t& entry) const {
  49.         return entry.state == State::Occupied;
  50.     }
  51.  
  52.     /*
  53.      * sets the state of the given position to deleted, when it
  54.      * was occupied.
  55.      *
  56.      * returns true, when possible,
  57.      * false otherwise.
  58.      */
  59.     bool remove(size_t pos) {
  60.         entry_t given = elements[pos].load();
  61.         entry_t replace = {State::Deleted, nullptr};
  62.         if (!isOccupied(given)) return false;
  63.         return elements[pos].compare_exchange_weak(
  64.                 given, replace);
  65.     }
  66.  
  67.     bool replaceWhenFree(size_t pos, entry_t insertEntry) {
  68.         entry_t expect = elements[pos].load();
  69.         if (!isFree(expect)) return false;
  70.         return elements[pos].compare_exchange_weak(
  71.                 expect, insertEntry);
  72.     }
  73.  
  74.     /*
  75.      * returns true when the element is contained, also stores
  76.      * the position of that element in "position"
  77.      */
  78.     bool contains(const T& key, size_t& position) const {
  79.         size_t pos = getHash(key);
  80.         size_t end = bound(pos-1);
  81.  
  82.         entry_t entry = elements[pos].load();
  83.  
  84.         while (pos != end && !isEmpty(entry)
  85.                 && !(isOccupied(entry) && entry.element == &key)) {
  86.             pos = bound(pos + 1);
  87.             entry = elements[pos].load();
  88.         }
  89.  
  90.         position = pos;
  91.         return isOccupied(entry) && entry.element == &key;
  92.     }
  93.  
  94.     /*
  95.      * searches for a deleted or empty position for the given key.
  96.      * returns the free position. aborts, when the element is already
  97.      * within.
  98.      */
  99.     size_t findFree(const T& key) const {
  100.         size_t pos = getHash(key);
  101.         size_t end = bound(pos-1);
  102.  
  103.         entry_t entry = elements[pos].load();
  104.         while (pos != end && isOccupied(entry)
  105.             && !(isOccupied(entry) && entry.element == &key)) {
  106.             pos = bound(pos+1);
  107.             entry = elements[pos].load();
  108.         }
  109.  
  110.         return pos;
  111.     }
  112.  
  113. public:
  114.     AtomicHashSet() : size_counter{0} {
  115.         for (size_t i = 0; i < max_size; i++) {
  116.             entry_t entry = {State::Empty, nullptr};
  117.             elements[i].store(entry);
  118.         }
  119.     }
  120.  
  121.     bool contains(const T& key) const {
  122.         size_t pos = 0;
  123.         return contains(key, pos);
  124.     }
  125.  
  126.     bool insert (const T& key) {
  127.         size_t pos = 0;
  128.         entry_t insertEntry = {State::Occupied, &key};
  129.  
  130.         bool success = false;
  131.  
  132.         do {
  133.             // this can only abort too early
  134.             if (size() == max_size) return false;
  135.  
  136.             // return if the element is already contained
  137.             bool contained = contains(key, pos);
  138.             if (contained) return false;
  139.  
  140.             // find free place
  141.             pos = findFree(key);
  142.  
  143.             // try to insert element
  144.             success = replaceWhenFree(pos, insertEntry);
  145.         } while (!success);
  146.  
  147.         size_counter++;
  148.  
  149.         return true;
  150.     }
  151.  
  152.     size_t size() const {
  153.         return size_counter.load();
  154.     }
  155.  
  156.     bool remove(const T& key) {
  157.         size_t pos = 0;
  158.         bool contained = contains(key, pos);
  159.         if (!contained) return false;
  160.         if (remove(pos)) {
  161.             size_counter--;
  162.             return true;
  163.         }
  164.         return false;
  165.     }
  166. };
  167.  
  168. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement