10 #include "llvm/ADT/DenseMap.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
20 const int TasksCnt = 100;
25 int IncrementsPerTask = 1000;
31 auto scheduleIncrements = [&]() {
32 for (
int TaskI = 0; TaskI < TasksCnt; ++TaskI) {
34 for (
int Increment = 0; Increment < IncrementsPerTask; ++Increment) {
35 std::lock_guard<std::mutex> Lock(Mutex);
45 std::lock_guard<std::mutex> Lock(Mutex);
51 std::lock_guard<std::mutex> Lock(Mutex);
52 ASSERT_EQ(
Counter, TasksCnt * IncrementsPerTask);
56 std::lock_guard<std::mutex> Lock(Mutex);
62 std::lock_guard<std::mutex> Lock(Mutex);
63 ASSERT_EQ(
Counter, TasksCnt * IncrementsPerTask);
67 const unsigned NumThreads = 5;
68 const unsigned NumKeys = 100;
69 const unsigned NumIterations = 100;
72 std::atomic<unsigned> ComputeCount(0);
73 std::atomic<int> ComputeResult[NumKeys];
74 std::fill(std::begin(ComputeResult), std::end(ComputeResult), -1);
77 for (
unsigned I = 0; I < NumThreads; ++I)
78 Tasks.
runAsync(
"worker" + std::to_string(I), [&] {
79 for (unsigned J = 0; J < NumIterations; J++)
80 for (unsigned K = 0; K < NumKeys; K++) {
81 int Result = Cache.get(K, [&] { return ++ComputeCount; });
82 EXPECT_THAT(ComputeResult[K].exchange(Result),
83 testing::AnyOf(-1, Result))
84 <<
"Got inconsistent results from memoize";
88 EXPECT_GE(ComputeCount, NumKeys) <<
"Computed each key once";
89 EXPECT_LE(ComputeCount, NumThreads * NumKeys)
90 <<
"Worst case, computed each key in every thread";
91 for (
int Result : ComputeResult)
92 EXPECT_GT(Result, 0) <<
"All results in expected domain";
102 std::atomic<char> ValueA(0), ValueB(0);
105 ValueA = Cache.
get(0, [&] {
112 ValueB = Cache.
get(0, [&] {
120 ASSERT_EQ(ValueA, ValueB);
121 ASSERT_THAT(ValueA.load(), testing::AnyOf(
'A',
'B'));