cxx11_eventcount.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2016 Dmitry Vyukov <dvyukov@google.com>
5 // Copyright (C) 2016 Benoit Steiner <benoit.steiner.goog@gmail.com>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #define EIGEN_USE_THREADS
12 #include "main.h"
13 #include <Eigen/CXX11/ThreadPool>
14 
15 // Visual studio doesn't implement a rand_r() function since its
16 // implementation of rand() is already thread safe
17 int rand_reentrant(unsigned int* s) {
18 #ifdef EIGEN_COMP_MSVC_STRICT
20  return rand();
21 #else
22  return rand_r(s);
23 #endif
24 }
25 
26 static void test_basic_eventcount()
27 {
29  waiters.resize(1);
30  EventCount ec(waiters);
31  EventCount::Waiter& w = waiters[0];
32  ec.Notify(false);
33  ec.Prewait();
34  ec.Notify(true);
35  ec.CommitWait(&w);
36  ec.Prewait();
37  ec.CancelWait();
38 }
39 
40 // Fake bounded counter-based queue.
41 struct TestQueue {
42  std::atomic<int> val_;
43  static const int kQueueSize = 10;
44 
45  TestQueue() : val_() {}
46 
47  ~TestQueue() { VERIFY_IS_EQUAL(val_.load(), 0); }
48 
49  bool Push() {
50  int val = val_.load(std::memory_order_relaxed);
51  for (;;) {
52  VERIFY_GE(val, 0);
53  VERIFY_LE(val, kQueueSize);
54  if (val == kQueueSize) return false;
55  if (val_.compare_exchange_weak(val, val + 1, std::memory_order_relaxed))
56  return true;
57  }
58  }
59 
60  bool Pop() {
61  int val = val_.load(std::memory_order_relaxed);
62  for (;;) {
63  VERIFY_GE(val, 0);
64  VERIFY_LE(val, kQueueSize);
65  if (val == 0) return false;
66  if (val_.compare_exchange_weak(val, val - 1, std::memory_order_relaxed))
67  return true;
68  }
69  }
70 
71  bool Empty() { return val_.load(std::memory_order_relaxed) == 0; }
72 };
73 
74 const int TestQueue::kQueueSize;
75 
76 // A number of producers send messages to a set of consumers using a set of
77 // fake queues. Ensure that it does not crash, consumers don't deadlock and
78 // number of blocked and unblocked threads match.
80 {
81  const int kThreads = std::thread::hardware_concurrency();
82  static const int kEvents = 1 << 16;
83  static const int kQueues = 10;
84 
85  MaxSizeVector<EventCount::Waiter> waiters(kThreads);
86  waiters.resize(kThreads);
87  EventCount ec(waiters);
88  TestQueue queues[kQueues];
89 
90  std::vector<std::unique_ptr<std::thread>> producers;
91  for (int i = 0; i < kThreads; i++) {
92  producers.emplace_back(new std::thread([&ec, &queues]() {
93  unsigned int rnd = static_cast<unsigned int>(std::hash<std::thread::id>()(std::this_thread::get_id()));
94  for (int j = 0; j < kEvents; j++) {
95  unsigned idx = rand_reentrant(&rnd) % kQueues;
96  if (queues[idx].Push()) {
97  ec.Notify(false);
98  continue;
99  }
101  j--;
102  }
103  }));
104  }
105 
106  std::vector<std::unique_ptr<std::thread>> consumers;
107  for (int i = 0; i < kThreads; i++) {
108  consumers.emplace_back(new std::thread([&ec, &queues, &waiters, i]() {
109  EventCount::Waiter& w = waiters[i];
110  unsigned int rnd = static_cast<unsigned int>(std::hash<std::thread::id>()(std::this_thread::get_id()));
111  for (int j = 0; j < kEvents; j++) {
112  unsigned idx = rand_reentrant(&rnd) % kQueues;
113  if (queues[idx].Pop()) continue;
114  j--;
115  ec.Prewait();
116  bool empty = true;
117  for (int q = 0; q < kQueues; q++) {
118  if (!queues[q].Empty()) {
119  empty = false;
120  break;
121  }
122  }
123  if (!empty) {
124  ec.CancelWait();
125  continue;
126  }
127  ec.CommitWait(&w);
128  }
129  }));
130  }
131 
132  for (int i = 0; i < kThreads; i++) {
133  producers[i]->join();
134  consumers[i]->join();
135  }
136 }
137 
138 EIGEN_DECLARE_TEST(cxx11_eventcount)
139 {
142 }
VERIFY_LE
#define VERIFY_LE(a, b)
Definition: main.h:383
w
RowVector3d w
Definition: Matrix_resize_int.cpp:3
test_stress_eventcount
static void test_stress_eventcount()
Definition: cxx11_eventcount.cpp:79
VERIFY_GE
#define VERIFY_GE(a, b)
Definition: main.h:382
s
RealScalar s
Definition: level1_cplx_impl.h:126
TestQueue::kQueueSize
static const int kQueueSize
Definition: cxx11_eventcount.cpp:43
VERIFY_IS_EQUAL
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:386
TestQueue::~TestQueue
~TestQueue()
Definition: cxx11_eventcount.cpp:47
EIGEN_THREAD_YIELD
#define EIGEN_THREAD_YIELD()
Definition: ThreadYield.h:17
TestQueue::Empty
bool Empty()
Definition: cxx11_eventcount.cpp:71
Eigen::EventCount::Prewait
void Prewait()
Definition: EventCount.h:66
EIGEN_DECLARE_TEST
EIGEN_DECLARE_TEST(cxx11_eventcount)
Definition: cxx11_eventcount.cpp:138
Eigen::EventCount::CancelWait
void CancelWait()
Definition: EventCount.h:109
EIGEN_UNUSED_VARIABLE
#define EIGEN_UNUSED_VARIABLE(var)
Definition: Macros.h:1076
j
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2
internal::Colamd::Empty
const int Empty
Definition: Eigen_Colamd.h:116
Eigen::numext::q
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:1984
TestQueue::Push
bool Push()
Definition: cxx11_eventcount.cpp:49
Eigen::EventCount::Notify
void Notify(bool notifyAll)
Definition: EventCount.h:130
empty
Definition: test_copy_move.cpp:19
main.h
TestQueue::val_
std::atomic< int > val_
Definition: cxx11_eventcount.cpp:42
Eigen::EventCount::CommitWait
void CommitWait(Waiter *w)
Definition: EventCount.h:79
Eigen::EventCount::Waiter
Definition: EventCount.h:167
rand_reentrant
int rand_reentrant(unsigned int *s)
Definition: cxx11_eventcount.cpp:17
TestQueue
Definition: cxx11_eventcount.cpp:41
Eigen::MaxSizeVector::resize
void resize(size_t n)
Definition: MaxSizeVector.h:69
test_basic_eventcount
static void test_basic_eventcount()
Definition: cxx11_eventcount.cpp:26
TestQueue::Pop
bool Pop()
Definition: cxx11_eventcount.cpp:60
TestQueue::TestQueue
TestQueue()
Definition: cxx11_eventcount.cpp:45
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
CALL_SUBTEST
#define CALL_SUBTEST(FUNC)
Definition: main.h:399
Eigen::MaxSizeVector
The MaxSizeVector class.
Definition: MaxSizeVector.h:31
Eigen::EventCount
Definition: EventCount.h:49


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:00:43