#include #include #include #include #include #include #include #include static_assert(sizeof(TCowString) == sizeof(const char*), "expect sizeof(TCowString) == sizeof(const char*)"); Y_UNIT_TEST_SUITE(CowPitfalls) { Y_UNIT_TEST(ParallelDetach) { // best results with thread-sanitizer std::vector> threads; TCowString a = "the string"; TCowString b = a; auto makeRefToA = [&a, &b]() { b = a; // make second reference to the same string }; constexpr int nThreads = 8; #ifdef _tsan_enabled_ constexpr i64 retries = 1'000; #else constexpr i64 retries = 1'000'000; #endif std::barrier iterationSyncPoint(nThreads, makeRefToA); std::atomic totalLen = 0; auto addLen = [](std::string a, std::atomic& len) { len += a.length(); }; auto workload = [&a, &addLen, &totalLen, &iterationSyncPoint]() { std::atomic len = 0; for (i64 j = 0; j < retries; ++j) { addLen(a, len); // possibility of bad implicit conversion iterationSyncPoint.arrive_and_wait(); } totalLen += len.load(); }; for (int i = 0; i < nThreads; ++i) { threads.push_back(std::make_unique(workload)); } for (auto& t : threads) { t->Start(); } for (auto& t : threads) { t->Join(); } UNIT_ASSERT_VALUES_EQUAL(totalLen.load(), b.size() * nThreads * retries); } } // Y_UNIT_TEST_SUITE(CowPitfalls)