// /************************************************************************ // * EOS - the CERN Disk Storage System * // * Copyright (C) 2023 CERN/Switzerland * // * * // * This program is free software: you can redistribute it and/or modify * // * it under the terms of the GNU General Public License as published by * // * the Free Software Foundation, either version 3 of the License, or * // * (at your option) any later version. * // * * // * This program is distributed in the hope that it will be useful, * // * but WITHOUT ANY WARRANTY; without even the implied warranty of * // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * // * GNU General Public License for more details. * // * * // * You should have received a copy of the GNU General Public License * // * along with this program. If not, see .* // ************************************************************************ // #include "common/concurrency/RCULite.hh" #include "common/concurrency/AtomicUniquePtr.h" #include "gtest/gtest.h" #include TEST(RCUTests, Basic) { using namespace eos::common; // Test that we can create an RCU object RCUDomain rcu_domain; atomic_unique_ptr ptr(new int(0)); int i{0}; // Test that we can create an RCU read lock auto read_fn = [&rcu_domain, &ptr](int index) { auto tid = experimental::tlocalID.get(); std::cout << "Starting reader at index=" << index << "tid=" << tid << std::endl; for (int j = 0; j < 100; ++j) { RCUReadLock rlock(rcu_domain); ASSERT_TRUE(ptr); } std::cout << "Done with reader at index= " << index << " tid=" << tid << std::endl; }; std::thread writer([&rcu_domain, &ptr, &i]() { std::cout << "Starting writer"; for (int j = 0; j < 5000; ++j) { int* old_ptr(nullptr); { RCUWriteLock wlock(rcu_domain); old_ptr = ptr.reset(new int(i++)); } std::cout << "."; delete old_ptr; std::this_thread::sleep_for(std::chrono::nanoseconds(1)); } }); std::vector readers; for (int k = 0; k < 100; ++k) { readers.emplace_back(read_fn, k); } for (int i = 0; i < 100; ++i) { readers[i].join(); } writer.join(); } TEST(RCUTests, BasicVersionCounter) { using namespace eos::common; // Test that we can create an RCU object VersionedRCUDomain rcu_domain; atomic_unique_ptr ptr(new int(0)); int i{0}; // Test that we can create an RCU read lock auto read_fn = [&rcu_domain, &ptr](int index) { auto tid = std::hash {}(std::this_thread::get_id()) % 4096; std::cout << "Starting reader at index=" << index << "tid=" << tid << std::endl; for (int j = 0; j < 100; ++j) { RCUReadLock rlock(rcu_domain); ASSERT_TRUE(ptr); } std::cout << "Done with reader at index= " << index << " tid=" << tid << std::endl; }; std::thread writer([&rcu_domain, &ptr, &i]() { std::cout << "Starting writer"; for (int j = 0; j < 5000; ++j) { rcu_domain.rcu_write_lock(); auto old_ptr = ptr.reset(new int(i++)); rcu_domain.rcu_synchronize(); std::cout << "."; delete old_ptr; std::this_thread::sleep_for(std::chrono::nanoseconds(1)); } }); std::vector readers; for (int k = 0; k < 100; ++k) { readers.emplace_back(read_fn, k); } for (int i = 0; i < 100; ++i) { readers[i].join(); } writer.join(); } // namespace eos::common