123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // This file is part of OpenCV project.
- // It is subject to the license terms in the LICENSE file found in the top-level directory
- // of this distribution and at http://opencv.org/license.html.
- //
- // Copyright (C) 2020 Intel Corporation
- #include "../test_precomp.hpp"
- #include <unordered_set>
- #include <thread>
- #include "executor/last_value.hpp"
- namespace opencv_test {
- using namespace cv::gapi;
- TEST(LastValue, PushPop) {
- own::last_written_value<int> v;
- for (int i = 0; i < 100; i++) {
- v.push(i);
- int x = 1;
- v.pop(x);
- EXPECT_EQ(i, x);
- }
- }
- TEST(LastValue, TryPop) {
- own::last_written_value<int> v;
- int x = 0;
- EXPECT_FALSE(v.try_pop(x));
- v.push(1);
- EXPECT_TRUE(v.try_pop(x));
- EXPECT_EQ(1, x);
- }
- TEST(LastValue, Clear) {
- own::last_written_value<int> v;
- v.push(42);
- v.clear();
- int x = 0;
- EXPECT_FALSE(v.try_pop(x));
- }
- TEST(LastValue, Overwrite) {
- own::last_written_value<int> v;
- v.push(42);
- v.push(0);
- int x = -1;
- EXPECT_TRUE(v.try_pop(x));
- EXPECT_EQ(0, x);
- }
- // In this test, every writer thread produces its own range of integer
- // numbers, writing those to a shared queue.
- //
- // Every reader thread pops elements from the queue (until -1 is
- // reached) and stores those in its own associated set.
- //
- // Finally, the master thread waits for completion of all other
- // threads and verifies that all the necessary data is
- // produced/obtained.
- namespace {
- using StressParam = std::tuple<int // Num writer threads
- ,int // Num elements per writer
- ,int>; // Num reader threads
- constexpr int STOP_SIGN = -1;
- constexpr int BASE = 1000;
- }
- struct LastValue_: public ::testing::TestWithParam<StressParam> {
- using V = own::last_written_value<int>;
- using S = std::unordered_set<int>;
- static void writer(int base, int writes, V& v) {
- for (int i = 0; i < writes; i++) {
- if (i % 2) {
- std::this_thread::sleep_for(std::chrono::milliseconds{1});
- }
- v.push(base + i);
- }
- v.push(STOP_SIGN);
- }
- static void reader(V& v, S& s) {
- int x = 0;
- while (true) {
- v.pop(x);
- if (x == STOP_SIGN) {
- // If this thread was lucky enough to read this STOP_SIGN,
- // push it back to v to make other possible readers able
- // to read it again (note due to the last_written_value
- // semantic, those STOP_SIGN could be simply lost i.e.
- // overwritten.
- v.push(STOP_SIGN);
- return;
- }
- s.insert(x);
- }
- }
- };
- TEST_P(LastValue_, Test)
- {
- int num_writers = 0;
- int num_writes = 0;
- int num_readers = 0;
- std::tie(num_writers, num_writes, num_readers) = GetParam();
- CV_Assert(num_writers < 20);
- CV_Assert(num_writes < BASE);
- V v;
- // Start reader threads
- std::vector<S> storage(num_readers);
- std::vector<std::thread> readers;
- for (S& s : storage) {
- readers.emplace_back(reader, std::ref(v), std::ref(s));
- }
- // Start writer threads, also pre-generate reference numbers
- S reference;
- std::vector<std::thread> writers;
- for (int w = 0; w < num_writers; w++) {
- writers.emplace_back(writer, w*BASE, num_writes, std::ref(v));
- for (int r = 0; r < num_writes; r++) {
- reference.insert(w*BASE + r);
- }
- }
- // Wait for completions
- for (auto &t : readers) t.join();
- for (auto &t : writers) t.join();
- // Validate the result. Some values are read, and the values are
- // correct (i.e. such values have been written)
- std::size_t num_values_read = 0u;
- for (const auto &s : storage) {
- num_values_read += s.size();
- for (auto &x : s) {
- EXPECT_TRUE(reference.count(x) > 0);
- }
- }
- // NOTE: Some combinations may end-up in 0 values read
- // it is normal, the main thing is that the test shouldn't hang!
- EXPECT_LE(0u, num_values_read);
- }
- INSTANTIATE_TEST_CASE_P(LastValueStress, LastValue_,
- Combine( Values(1, 2, 4, 8, 16) // writers
- , Values(32, 96, 256) // writes
- , Values(1, 2, 10))); // readers
- } // namespace opencv_test
|