last_written_value_tests.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //
  5. // Copyright (C) 2020 Intel Corporation
  6. #include "../test_precomp.hpp"
  7. #include <unordered_set>
  8. #include <thread>
  9. #include "executor/last_value.hpp"
  10. namespace opencv_test {
  11. using namespace cv::gapi;
  12. TEST(LastValue, PushPop) {
  13. own::last_written_value<int> v;
  14. for (int i = 0; i < 100; i++) {
  15. v.push(i);
  16. int x = 1;
  17. v.pop(x);
  18. EXPECT_EQ(i, x);
  19. }
  20. }
  21. TEST(LastValue, TryPop) {
  22. own::last_written_value<int> v;
  23. int x = 0;
  24. EXPECT_FALSE(v.try_pop(x));
  25. v.push(1);
  26. EXPECT_TRUE(v.try_pop(x));
  27. EXPECT_EQ(1, x);
  28. }
  29. TEST(LastValue, Clear) {
  30. own::last_written_value<int> v;
  31. v.push(42);
  32. v.clear();
  33. int x = 0;
  34. EXPECT_FALSE(v.try_pop(x));
  35. }
  36. TEST(LastValue, Overwrite) {
  37. own::last_written_value<int> v;
  38. v.push(42);
  39. v.push(0);
  40. int x = -1;
  41. EXPECT_TRUE(v.try_pop(x));
  42. EXPECT_EQ(0, x);
  43. }
  44. // In this test, every writer thread produces its own range of integer
  45. // numbers, writing those to a shared queue.
  46. //
  47. // Every reader thread pops elements from the queue (until -1 is
  48. // reached) and stores those in its own associated set.
  49. //
  50. // Finally, the master thread waits for completion of all other
  51. // threads and verifies that all the necessary data is
  52. // produced/obtained.
  53. namespace {
  54. using StressParam = std::tuple<int // Num writer threads
  55. ,int // Num elements per writer
  56. ,int>; // Num reader threads
  57. constexpr int STOP_SIGN = -1;
  58. constexpr int BASE = 1000;
  59. }
  60. struct LastValue_: public ::testing::TestWithParam<StressParam> {
  61. using V = own::last_written_value<int>;
  62. using S = std::unordered_set<int>;
  63. static void writer(int base, int writes, V& v) {
  64. for (int i = 0; i < writes; i++) {
  65. if (i % 2) {
  66. std::this_thread::sleep_for(std::chrono::milliseconds{1});
  67. }
  68. v.push(base + i);
  69. }
  70. v.push(STOP_SIGN);
  71. }
  72. static void reader(V& v, S& s) {
  73. int x = 0;
  74. while (true) {
  75. v.pop(x);
  76. if (x == STOP_SIGN) {
  77. // If this thread was lucky enough to read this STOP_SIGN,
  78. // push it back to v to make other possible readers able
  79. // to read it again (note due to the last_written_value
  80. // semantic, those STOP_SIGN could be simply lost i.e.
  81. // overwritten.
  82. v.push(STOP_SIGN);
  83. return;
  84. }
  85. s.insert(x);
  86. }
  87. }
  88. };
  89. TEST_P(LastValue_, Test)
  90. {
  91. int num_writers = 0;
  92. int num_writes = 0;
  93. int num_readers = 0;
  94. std::tie(num_writers, num_writes, num_readers) = GetParam();
  95. CV_Assert(num_writers < 20);
  96. CV_Assert(num_writes < BASE);
  97. V v;
  98. // Start reader threads
  99. std::vector<S> storage(num_readers);
  100. std::vector<std::thread> readers;
  101. for (S& s : storage) {
  102. readers.emplace_back(reader, std::ref(v), std::ref(s));
  103. }
  104. // Start writer threads, also pre-generate reference numbers
  105. S reference;
  106. std::vector<std::thread> writers;
  107. for (int w = 0; w < num_writers; w++) {
  108. writers.emplace_back(writer, w*BASE, num_writes, std::ref(v));
  109. for (int r = 0; r < num_writes; r++) {
  110. reference.insert(w*BASE + r);
  111. }
  112. }
  113. // Wait for completions
  114. for (auto &t : readers) t.join();
  115. for (auto &t : writers) t.join();
  116. // Validate the result. Some values are read, and the values are
  117. // correct (i.e. such values have been written)
  118. std::size_t num_values_read = 0u;
  119. for (const auto &s : storage) {
  120. num_values_read += s.size();
  121. for (auto &x : s) {
  122. EXPECT_TRUE(reference.count(x) > 0);
  123. }
  124. }
  125. // NOTE: Some combinations may end-up in 0 values read
  126. // it is normal, the main thing is that the test shouldn't hang!
  127. EXPECT_LE(0u, num_values_read);
  128. }
  129. INSTANTIATE_TEST_CASE_P(LastValueStress, LastValue_,
  130. Combine( Values(1, 2, 4, 8, 16) // writers
  131. , Values(32, 96, 256) // writes
  132. , Values(1, 2, 10))); // readers
  133. } // namespace opencv_test