File: kirsch_kfifo_queue_test.cpp

package info (click to toggle)
xenium 0.0.2%2Bds-10
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,152 kB
  • sloc: cpp: 12,299; makefile: 20
file content (129 lines) | stat: -rw-r--r-- 3,962 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <xenium/reclamation/hazard_pointer.hpp>
#include <xenium/reclamation/hazard_eras.hpp>
#include <xenium/reclamation/quiescent_state_based.hpp>
#include <xenium/reclamation/generic_epoch_based.hpp>
#include <xenium/reclamation/stamp_it.hpp>
#include <xenium/kirsch_kfifo_queue.hpp>

#include <gtest/gtest.h>

#include <vector>
#include <thread>

namespace {

template <typename Reclaimer>
struct KirschKFifoQueue : testing::Test {};

int* v1 = new int(42);
int* v2 = new int(43);

using Reclaimers = ::testing::Types<
    xenium::reclamation::hazard_pointer<>::with<
      xenium::policy::allocation_strategy<xenium::reclamation::hp_allocation::static_strategy<2>>>,
    xenium::reclamation::hazard_eras<>::with<
      xenium::policy::allocation_strategy<xenium::reclamation::he_allocation::static_strategy<2>>>,
    xenium::reclamation::quiescent_state_based,
    xenium::reclamation::debra<>::with<xenium::policy::scan_frequency<10>>,
    xenium::reclamation::epoch_based<>::with<xenium::policy::scan_frequency<10>>,
    xenium::reclamation::new_epoch_based<>::with<xenium::policy::scan_frequency<10>>,
    xenium::reclamation::stamp_it
  >;
TYPED_TEST_CASE(KirschKFifoQueue, Reclaimers);

TYPED_TEST(KirschKFifoQueue, push_try_pop_returns_pushed_element)
{
  xenium::kirsch_kfifo_queue<int*, xenium::policy::reclaimer<TypeParam>> queue(1);
  queue.push(v1);
  int* elem;
  EXPECT_TRUE(queue.try_pop(elem));
  EXPECT_EQ(v1, elem);
}

TYPED_TEST(KirschKFifoQueue, supports_unique_ptr)
{
  xenium::kirsch_kfifo_queue<std::unique_ptr<int>, xenium::policy::reclaimer<TypeParam>> queue(1);
  auto p = new int(42);
  std::unique_ptr<int> elem(p);
  queue.push(std::move(elem));
  ASSERT_TRUE(queue.try_pop(elem));
  EXPECT_EQ(p, elem.get());
  EXPECT_EQ(42, *elem);
}

TYPED_TEST(KirschKFifoQueue, deletes_remaining_unique_ptr_entries)
{
  unsigned delete_count = 0;
  struct dummy {
    unsigned& delete_count;
    dummy(unsigned& delete_count) : delete_count(delete_count) {}
    ~dummy() { ++delete_count; }
  };
  {
    xenium::kirsch_kfifo_queue<std::unique_ptr<dummy>, xenium::policy::reclaimer<TypeParam>> queue(1);
      for (int i = 0; i < 200; ++i)
    queue.push(std::make_unique<dummy>(delete_count));
  }
  EXPECT_EQ(200u, delete_count);
}

TYPED_TEST(KirschKFifoQueue, push_two_items_pop_them_in_FIFO_order)
{
  xenium::kirsch_kfifo_queue<int*, xenium::policy::reclaimer<TypeParam>> queue(1);
  queue.push(v1);
  queue.push(v2);
  int* elem1;
  int* elem2;
  EXPECT_TRUE(queue.try_pop(elem1));
  EXPECT_TRUE(queue.try_pop(elem2));
  EXPECT_EQ(v1, elem1);
  EXPECT_EQ(v2, elem2);
}

TYPED_TEST(KirschKFifoQueue, push_large_number_of_entries_pop_them_in_FIFO_order)
{
  [[maybe_unused]] typename TypeParam::region_guard guard{};
  xenium::kirsch_kfifo_queue<int*, xenium::policy::reclaimer<TypeParam>> queue(1);
  for (int i = 0; i < 1000; ++i)
    queue.push(new int(i));
  
  int* elem;
  for (int i = 0; i < 1000; ++i) {
    ASSERT_TRUE(queue.try_pop(elem));
    EXPECT_EQ(i, *elem);
  }
}

TYPED_TEST(KirschKFifoQueue, parallel_usage)
{
  using Reclaimer = TypeParam;
  xenium::kirsch_kfifo_queue<int*, xenium::policy::reclaimer<TypeParam>> queue(8);

  std::vector<std::thread> threads;
  for (int i = 0; i < 4; ++i)
  {
    threads.push_back(std::thread([i, &queue]
    {
    #ifdef DEBUG
      const int MaxIterations = 1000;
    #else
      const int MaxIterations = 10000;
    #endif
      for (int j = 0; j < MaxIterations; ++j)
      {
        [[maybe_unused]] typename Reclaimer::region_guard guard{};
        for (int k = 0; k < 10; ++k) {
          queue.push(new int(i));
          int* elem = nullptr;
          EXPECT_TRUE(queue.try_pop(elem));
          EXPECT_TRUE(*elem >= 0 && *elem <= 4);
          delete elem;
        }
      }
    }));
  }

  for (auto& thread : threads)
    thread.join();
}
}