BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
threadsafestack.test.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // qt-mvvm: Model-view-view-model framework for large GUI applications
4 //
5 //! @file mvvm/tests/testmodel/threadsafestack.test.cpp
6 //! @brief Implements class CLASS?
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Gennady Pospelov et al, Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "google_test.h"
17 #include <future>
18 
19 using namespace ModelView;
20 
21 //! Testing AxisItems.
22 
23 class ThreadSafeStackTest : public ::testing::Test {
24 public:
26 };
27 
29 
30 //! Checking stack initial state (single thread mode).
31 
33 {
35  EXPECT_TRUE(stack.empty());
36  int value;
37  EXPECT_FALSE(stack.try_pop(value));
38 
39  auto sh_value = stack.try_pop();
40  EXPECT_FALSE(sh_value);
41 }
42 
43 //! Push and then pop (single thread mode).
44 
46 {
48 
49  stack.push(42);
50  EXPECT_FALSE(stack.empty());
51  int value(0);
52  EXPECT_TRUE(stack.try_pop(value));
53  EXPECT_EQ(value, 42);
54 
55  stack.push(43);
56  auto result = stack.wait_and_pop();
57  EXPECT_EQ(*result.get(), 43);
58 }
59 
60 //! Update top value (single thread mode).
61 
63 {
65 
66  // update of empty stack means simple appearance of value
67  stack.update_top(42);
68  EXPECT_FALSE(stack.empty());
69  int value(0);
70  EXPECT_TRUE(stack.try_pop(value));
71  EXPECT_EQ(value, 42);
72 
73  // updating value
74  stack.push(43);
75  stack.update_top(44);
76  auto result = stack.wait_and_pop();
77  EXPECT_EQ(*result.get(), 44);
78 
79  // shouldn't be more values
80  auto sh_value = stack.try_pop();
81  EXPECT_FALSE(sh_value);
82 }
83 
84 //! Push and pop in concurrent mode.
85 //! Test is borrowed from Anthony Williams, C++ Concurrency in Action, Second edition.
86 
87 TEST_F(ThreadSafeStackTest, concurentPushAndPop)
88 {
90  std::promise<void> go, push_ready_for_test, pop_ready_for_test;
91  std::shared_future<void> ready(go.get_future());
92  std::future<void> push_done;
93  std::future<std::shared_ptr<int>> pop_done;
94 
95  try {
96  // starting pushing thread
97  push_done = std::async(std::launch::async, [&stack, ready, &push_ready_for_test]() {
98  push_ready_for_test.set_value();
99  ready.wait();
100  stack.push(42);
101  });
102 
103  // starting pop thread
104  pop_done = std::async(std::launch::async, [&stack, ready, &pop_ready_for_test]() {
105  pop_ready_for_test.set_value();
106  ready.wait();
107  return stack.wait_and_pop();
108  });
109 
110  // waiting for threads being prepared for racing
111  push_ready_for_test.get_future().wait();
112  pop_ready_for_test.get_future().wait();
113 
114  // starting concurrent push and pop
115  go.set_value();
116 
117  // checking result
118  push_done.get(); // making sure pushing thread has finished
119 
120  EXPECT_EQ(*pop_done.get(), 42);
121  EXPECT_TRUE(stack.empty());
122 
123  } catch (...) {
124  go.set_value();
125  throw;
126  }
127 }
128 
129 //! Explicitely terminate waiting (concurrent mode).
130 
131 TEST_F(ThreadSafeStackTest, concurentStopWaiting)
132 {
133  threadsafe_stack<int> stack;
134  std::promise<void> go, pop_ready_for_test;
135  std::shared_future<void> ready(go.get_future());
136  std::future<std::shared_ptr<int>> pop_done;
137 
138  try {
139  // starting pop thread
140  pop_done = std::async(std::launch::async, [&stack, ready, &pop_ready_for_test]() {
141  pop_ready_for_test.set_value();
142  ready.wait();
143  return stack.wait_and_pop();
144  });
145 
146  // waiting for threads being prepared for racing
147  pop_ready_for_test.get_future().wait();
148 
149  // starting waiting on empty stack
150  go.set_value();
151 
152  // stopping waiting
153  stack.stop();
154 
155  // stopping stack will raise exception
156  EXPECT_THROW(*pop_done.get(), empty_stack);
157  EXPECT_TRUE(stack.empty());
158 
159  } catch (...) {
160  go.set_value();
161  throw;
162  }
163 }
Thread-safe stack borrowed from Anthony Williams, C++ Concurrency in Action, Second edition.
void update_top(T new_value)
Updates top value in a stack.
void stop()
Terminates waiting in wait_and_pop methods.
Defines class CLASS?
materialitems.h Collection of materials to populate MaterialModel.
Defines class CLASS?
TEST_F(ThreadSafeStackTest, initialState)
Checking stack initial state (single thread mode).