From 0c7313bb5f2baa2fb2c95ddff001601083737fca Mon Sep 17 00:00:00 2001
From: Matej Ferencevic <matej.ferencevic@memgraph.io>
Date: Fri, 24 Jan 2020 10:22:34 +0100
Subject: [PATCH] Remove unused datastructures

Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2639
---
 src/data_structures/bitset/static_bitset.hpp |  99 ------------
 src/data_structures/queue.hpp                |  90 -----------
 src/data_structures/union_find.hpp           |  90 -----------
 tests/unit/CMakeLists.txt                    |   6 -
 tests/unit/datastructure_union_find.cpp      |  80 ----------
 tests/unit/queue.cpp                         | 154 -------------------
 6 files changed, 519 deletions(-)
 delete mode 100644 src/data_structures/bitset/static_bitset.hpp
 delete mode 100644 src/data_structures/queue.hpp
 delete mode 100644 src/data_structures/union_find.hpp
 delete mode 100644 tests/unit/datastructure_union_find.cpp
 delete mode 100644 tests/unit/queue.cpp

diff --git a/src/data_structures/bitset/static_bitset.hpp b/src/data_structures/bitset/static_bitset.hpp
deleted file mode 100644
index 0a0300aac..000000000
--- a/src/data_structures/bitset/static_bitset.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <bitset>
-#include <iostream>
-#include <string>
-
-#include "glog/logging.h"
-
-/**
- * Bitset data structure with a number of bits provided in constructor.
- * @tparam TStore type of underlying bit storage: int32, int64, char, etc.
- */
-template <typename TStore>
-class Bitset {
- public:
-  /**
-   *  Create bitset.
-   *  @param sz size of bitset
-   */
-  Bitset(size_t sz) : block_size_(8 * sizeof(TStore)) {
-    if (sz % block_size_ != 0) sz += block_size_;
-    blocks_.resize(sz / block_size_);
-  }
-  /**
-   *  Set bit to one.
-   *  @param idx position of bit.
-   */
-  void Set(int idx) {
-    DCHECK(idx >= 0) << "Invalid bit location.";
-    DCHECK(idx < static_cast<int64_t>(blocks_.size()) * block_size_)
-        << "Invalid bit location.";
-    int bucket = idx / block_size_;
-    blocks_[bucket] |= TStore(1) << idx % block_size_;
-  }
-  /**
-   *  Return bit at position.
-   *  @param idx position of bit.
-   *  @return 1/0.
-   */
-  bool At(int idx) const {
-    DCHECK(idx >= 0) << "Invalid bit location.";
-    DCHECK(idx < static_cast<int64_t>(blocks_.size()) * block_size_)
-        << "Invalid bit location.";
-    int bucket = idx / block_size_;
-    return (blocks_[bucket] >> (idx % block_size_)) & 1;
-  }
-  /**
-   *  Intersect two bitsets
-   *  @param other bitset.
-   *  @return intersection.
-   */
-  Bitset<TStore> Intersect(const Bitset<TStore> &other) const {
-    DCHECK(this->blocks_.size() == other.blocks_.size())
-        << "Bitsets are not of equal size.";
-    Bitset<TStore> ret(this->blocks_.size() * this->block_size_);
-    for (int i = 0; i < (int)this->blocks_.size(); ++i) {
-      ret.blocks_[i] = this->blocks_[i] & other.blocks_[i];
-      continue;
-    }
-    return ret;
-  }
-  /**
-   *  Positions of bits set to 1.
-   *  @return positions of bits set to 1.
-   */
-  std::vector<int> Ones() const {
-    std::vector<int> ret;
-    int ret_idx = 0;
-    for (auto x : blocks_) {
-      while (x) {
-        auto pos = CountTrailingZeroes(x & -x);
-        x -= x & -x;
-        ret.push_back(ret_idx + pos);
-      }
-      ret_idx += block_size_;
-    }
-    return ret;
-  }
-
- private:
-  /**
-   * Calculate number of trailing zeroes in a binary number, usually a power
-   * of two.
-   * @return number of trailing zeroes.
-   */
-  size_t CountTrailingZeroes(TStore v) const {
-    size_t ret = 0;
-    while (v >> 32) ret += 32, v >>= 32;
-    if (v >> 16) ret += 16, v >>= 16;
-    if (v >> 8) ret += 8, v >>= 8;
-    if (v >> 4) ret += 4, v >>= 4;
-    if (v >> 2) ret += 2, v >>= 2;
-    if (v >> 1) ret += 1, v >>= 1;
-    return ret;
-  }
-  std::vector<TStore> blocks_;
-  const size_t block_size_;
-};
diff --git a/src/data_structures/queue.hpp b/src/data_structures/queue.hpp
deleted file mode 100644
index ffaa738db..000000000
--- a/src/data_structures/queue.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-#include <atomic>
-#include <condition_variable>
-#include <cstdint>
-#include <iostream>
-#include <mutex>
-#include <optional>
-#include <queue>
-#include <thread>
-
-#include "glog/logging.h"
-
-// Thread safe queue. Probably doesn't perform very well, but it works.
-template <typename T>
-class Queue {
- public:
-  Queue() = default;
-  Queue(const Queue &) = delete;
-  Queue &operator=(const Queue &) = delete;
-  Queue(Queue &&) = delete;
-  Queue &operator=(Queue &&) = delete;
-
-  void Push(T x) {
-    std::unique_lock<std::mutex> guard(mutex_);
-    queue_.emplace(std::move(x));
-    guard.unlock();
-    cvar_.notify_one();
-  }
-
-  template <typename... Args>
-  void Emplace(Args &&... args) {
-    std::unique_lock<std::mutex> guard(mutex_);
-    queue_.emplace(std::forward<Args>(args)...);
-    guard.unlock();
-    cvar_.notify_one();
-  }
-
-  int64_t size() const {
-    std::unique_lock<std::mutex> guard(mutex_);
-    return queue_.size();
-  }
-
-  bool empty() const {
-    std::unique_lock<std::mutex> guard(mutex_);
-    return queue_.empty();
-  }
-
-  // Block until there is an element in the queue and then pop it from the queue
-  // and return it. Function can return nullopt if Queue is signaled via
-  // Shutdown function or if there is no element to pop after timeout elapses.
-  std::optional<T> AwaitPop(std::chrono::system_clock::duration timeout =
-                                std::chrono::system_clock::duration::max()) {
-    std::unique_lock<std::mutex> guard(mutex_);
-    auto now = std::chrono::system_clock::now();
-    auto until = std::chrono::system_clock::time_point::max() - timeout > now
-                     ? now + timeout
-                     : std::chrono::system_clock::time_point::max();
-    cvar_.wait_until(guard, until,
-                     [this] { return !queue_.empty() || !alive_; });
-    if (queue_.empty() || !alive_) return std::nullopt;
-    std::optional<T> x(std::move(queue_.front()));
-    queue_.pop();
-    return x;
-  }
-
-  // Nonblocking version of above function.
-  std::optional<T> MaybePop() {
-    std::unique_lock<std::mutex> guard(mutex_);
-    if (queue_.empty()) return std::nullopt;
-    std::optional<T> x(std::move(queue_.front()));
-    queue_.pop();
-    return x;
-  }
-
-  // Notify all threads waiting on conditional variable to stop waiting. New
-  // threads that try to Await will not block.
-  void Shutdown() {
-    std::unique_lock<std::mutex> guard(mutex_);
-    alive_ = false;
-    guard.unlock();
-    cvar_.notify_all();
-  }
-
- private:
-  bool alive_ = true;
-  std::queue<T> queue_;
-  std::condition_variable cvar_;
-  mutable std::mutex mutex_;
-};
diff --git a/src/data_structures/union_find.hpp b/src/data_structures/union_find.hpp
deleted file mode 100644
index 98e3fd92d..000000000
--- a/src/data_structures/union_find.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <vector>
-
-template <class uintXX_t = uint32_t>
-/**
- * UnionFind data structure. Provides means of connectivity
- * setting and checking in O(alpha(n)) amortized complexity. Memory
- * complexity is linear.
- */
-class UnionFind {
- public:
-  /**
-   * Constructor, creates a UnionFind structure of fixed size.
-   *
-   * @param n Number of elements in the data structure.
-   */
-  explicit UnionFind(uintXX_t n) : set_count_(n), rank_(n), parent_(n) {
-    for (auto i = 0; i < n; ++i) rank_[i] = 0, parent_[i] = i;
-  }
-
-  /**
-   * Connects two elements (and thereby the sets they belong
-   * to). If they are already connected the function has no effect.
-   *
-   * Has O(alpha(n)) amortized time complexity.
-   *
-   * @param p First element.
-   * @param q Second element.
-   */
-  void Connect(uintXX_t p, uintXX_t q) {
-    auto rp = Root(p);
-    auto rq = Root(q);
-
-    // if roots are equal, we don't have to do anything
-    if (rp == rq) return;
-
-    // merge the subtree with the smaller rank to the root of the subtree with
-    // the larger rank
-    if (rank_[rp] < rank_[rq])
-      parent_[rp] = rq;
-    else if (rank_[rp] > rank_[rq])
-      parent_[rq] = rp;
-    else
-      parent_[rq] = rp, rank_[rp] += 1;
-
-    // update the number of groups
-    set_count_--;
-  }
-
-  /**
-   * Indicates if two elements are connected. Has amortized O(alpha(n)) time
-   * complexity.
-   *
-   * @param p First element.
-   * @param q Second element.
-   * @return See above.
-   */
-  bool Find(uintXX_t p, uintXX_t q) { return Root(p) == Root(q); }
-
-  /**
-   * Returns the number of disjoint sets in this UnionFind.
-   *
-   * @return See above.
-   */
-  uintXX_t Size() const { return set_count_; }
-
- private:
-  uintXX_t set_count_;
-
-  // array of subtree ranks
-  std::vector<uintXX_t> rank_;
-
-  // array of tree indices
-  std::vector<uintXX_t> parent_;
-
-  uintXX_t Root(uintXX_t p) {
-    auto r = p;
-    auto newp = p;
-
-    // find the node connected to itself, that's the root
-    while (parent_[r] != r) r = parent_[r];
-
-    // do some path compression to enable faster searches
-    while (p != r) newp = parent_[p], parent_[p] = r, p = newp;
-
-    return r;
-  }
-};
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index ef396303e..0850bc20f 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -24,9 +24,6 @@ target_link_libraries(${test_prefix}bolt_encoder mg-communication mg-query)
 add_unit_test(commit_log_v2.cpp)
 target_link_libraries(${test_prefix}commit_log_v2 glog gflags)
 
-add_unit_test(datastructure_union_find.cpp)
-target_link_libraries(${test_prefix}datastructure_union_find glog gflags)
-
 add_unit_test(kvstore.cpp)
 target_link_libraries(${test_prefix}kvstore kvstore_lib glog)
 
@@ -112,9 +109,6 @@ target_link_libraries(${test_prefix}typed_value mg-query)
 
 # END mg-query
 
-add_unit_test(queue.cpp)
-target_link_libraries(${test_prefix}queue glog gflags)
-
 add_unit_test(skip_list.cpp)
 target_link_libraries(${test_prefix}skip_list mg-utils)
 
diff --git a/tests/unit/datastructure_union_find.cpp b/tests/unit/datastructure_union_find.cpp
deleted file mode 100644
index 73c450662..000000000
--- a/tests/unit/datastructure_union_find.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <stdlib.h>
-#include <iostream>
-
-#include "gtest/gtest.h"
-
-#include "data_structures/union_find.hpp"
-
-void ExpectFully(UnionFind<> &uf, bool connected, int from = 0, int to = -1) {
-  if (to == -1) to = uf.Size();
-
-  for (int i = from; i < to; i++)
-    for (int j = from; j < to; j++)
-      if (i != j) EXPECT_EQ(uf.Find(i, j), connected);
-}
-
-TEST(UnionFindTest, InitialSizeTest) {
-  for (int i = 0; i < 10; i++) {
-    UnionFind<> uf(i);
-    EXPECT_EQ(i, uf.Size());
-  }
-}
-
-TEST(UnionFindTest, ModifiedSizeTest) {
-  UnionFind<> uf(10);
-  EXPECT_EQ(10, uf.Size());
-
-  uf.Connect(0, 0);
-  EXPECT_EQ(10, uf.Size());
-
-  uf.Connect(0, 1);
-  EXPECT_EQ(9, uf.Size());
-
-  uf.Connect(2, 3);
-  EXPECT_EQ(8, uf.Size());
-
-  uf.Connect(0, 2);
-  EXPECT_EQ(7, uf.Size());
-
-  uf.Connect(1, 3);
-  EXPECT_EQ(7, uf.Size());
-}
-
-TEST(UnionFindTest, Disconectivity) {
-  UnionFind<> uf(10);
-  ExpectFully(uf, false);
-}
-
-TEST(UnionFindTest, ConnectivityAlongChain) {
-  UnionFind<> uf(10);
-  for (unsigned int i = 1; i < uf.Size(); i++) uf.Connect(i - 1, i);
-  ExpectFully(uf, true);
-}
-
-TEST(UnionFindTest, ConnectivityOnTree) {
-  UnionFind<> uf(10);
-  ExpectFully(uf, false);
-
-  uf.Connect(0, 1);
-  uf.Connect(0, 2);
-  ExpectFully(uf, true, 0, 3);
-  ExpectFully(uf, false, 2);
-
-  uf.Connect(2, 3);
-  ExpectFully(uf, true, 0, 4);
-  ExpectFully(uf, false, 3);
-}
-
-TEST(UnionFindTest, DisjointChains) {
-  UnionFind<> uf(30);
-  for (int i = 0; i < 30; i++) uf.Connect(i, i % 10 == 0 ? i : i - 1);
-
-  for (int i = 0; i < 30; i++)
-    for (int j = 0; j < 30; j++)
-      EXPECT_EQ(uf.Find(i, j), (j - (j % 10)) == (i - (i % 10)));
-}
-
-int main(int argc, char **argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp
deleted file mode 100644
index e46148e3e..000000000
--- a/tests/unit/queue.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-#include <atomic>
-#include <chrono>
-#include <optional>
-#include <string>
-#include <thread>
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-#include "data_structures/queue.hpp"
-
-namespace {
-
-using namespace std::literals::chrono_literals;
-
-TEST(Queue, PushMaybePop) {
-  Queue<int> q;
-  q.Push(1);
-  EXPECT_EQ(*q.MaybePop(), 1);
-  EXPECT_EQ(q.MaybePop(), std::nullopt);
-
-  q.Push(2);
-  q.Push(3);
-  EXPECT_EQ(*q.MaybePop(), 2);
-
-  q.Push(4);
-  q.Push(5);
-  EXPECT_EQ(*q.MaybePop(), 3);
-  EXPECT_EQ(*q.MaybePop(), 4);
-  EXPECT_EQ(*q.MaybePop(), 5);
-  EXPECT_EQ(q.MaybePop(), std::nullopt);
-}
-
-TEST(Queue, Emplace) {
-  Queue<std::pair<std::string, int>> q;
-  q.Emplace("abc", 123);
-  EXPECT_THAT(*q.MaybePop(), testing::Pair("abc", 123));
-}
-
-TEST(Queue, Size) {
-  Queue<int> q;
-  EXPECT_EQ(q.size(), 0);
-
-  q.Push(1);
-  EXPECT_EQ(q.size(), 1);
-
-  q.Push(1);
-  EXPECT_EQ(q.size(), 2);
-
-  q.MaybePop();
-  EXPECT_EQ(q.size(), 1);
-
-  q.MaybePop();
-  EXPECT_EQ(q.size(), 0);
-  q.MaybePop();
-  EXPECT_EQ(q.size(), 0);
-}
-
-TEST(Queue, Empty) {
-  Queue<int> q;
-  EXPECT_TRUE(q.empty());
-
-  q.Push(1);
-  EXPECT_FALSE(q.empty());
-
-  q.MaybePop();
-  EXPECT_TRUE(q.empty());
-}
-
-TEST(Queue, AwaitPop) {
-  Queue<int> q;
-  std::thread t([&] {
-    q.Push(1);
-    q.Push(2);
-    std::this_thread::sleep_for(200ms);
-    q.Push(3);
-    q.Push(4);
-  });
-
-  EXPECT_EQ(*q.AwaitPop(), 1);
-  std::this_thread::sleep_for(1000ms);
-  EXPECT_EQ(*q.AwaitPop(), 2);
-  EXPECT_EQ(*q.AwaitPop(), 3);
-  EXPECT_EQ(*q.AwaitPop(), 4);
-  t.join();
-
-  std::thread t2([&] {
-    std::this_thread::sleep_for(100ms);
-    q.Shutdown();
-  });
-  std::this_thread::sleep_for(200ms);
-  EXPECT_EQ(q.AwaitPop(), std::nullopt);
-  t2.join();
-}
-
-TEST(Queue, AwaitPopTimeout) {
-  std::this_thread::sleep_for(1000ms);
-  Queue<int> q;
-  EXPECT_EQ(q.AwaitPop(100ms), std::nullopt);
-}
-
-TEST(Queue, Concurrent) {
-  Queue<int> q;
-
-  const int kNumProducers = 10;
-  const int kNumConsumers = 10;
-  const int kNumElementsPerProducer = 300000;
-
-  std::vector<std::thread> producers;
-  std::atomic<int> next{0};
-
-  for (int i = 0; i < kNumProducers; ++i) {
-    producers.emplace_back([&] {
-      for (int i = 0; i < kNumElementsPerProducer; ++i) {
-        q.Push(next++);
-      }
-    });
-  }
-
-  std::vector<std::thread> consumers;
-  std::vector<int> retrieved[kNumConsumers];
-  std::atomic<int> num_retrieved{0};
-  for (int i = 0; i < kNumConsumers; ++i) {
-    consumers.emplace_back(
-        [&](int thread_id) {
-          while (true) {
-            int count = num_retrieved++;
-            if (count >= kNumProducers * kNumElementsPerProducer) break;
-            retrieved[thread_id].push_back(*q.AwaitPop());
-          }
-        },
-        i);
-  }
-
-  for (auto &t : consumers) {
-    t.join();
-  }
-  for (auto &t : producers) {
-    t.join();
-  }
-
-  EXPECT_EQ(q.MaybePop(), std::nullopt);
-
-  std::set<int> all_elements;
-  for (auto &r : retrieved) {
-    all_elements.insert(r.begin(), r.end());
-  }
-  EXPECT_EQ(all_elements.size(), kNumProducers * kNumElementsPerProducer);
-  EXPECT_EQ(*all_elements.begin(), 0);
-  EXPECT_EQ(*all_elements.rbegin(),
-            kNumProducers * kNumElementsPerProducer - 1);
-}
-}  // namespace