xref: /aosp_15_r20/external/angle/src/common/SimpleMutex_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SimpleMutex_unittest:
7 //   Tests of the SimpleMutex class
8 //
9 
10 #include <gtest/gtest.h>
11 
12 #include "common/SimpleMutex.h"
13 
14 namespace angle
15 {
16 namespace
17 {
18 template <typename TestMutex>
runBasicMutexTest()19 bool runBasicMutexTest()
20 {
21     constexpr size_t kThreadCount    = 16;
22     constexpr size_t kIterationCount = 50'000;
23 
24     std::array<std::thread, kThreadCount> threads;
25 
26     std::mutex mutex;
27     std::condition_variable condVar;
28     size_t readyCount = 0;
29 
30     TestMutex testMutex;
31     std::atomic<size_t> testVar;
32 
33     for (size_t i = 0; i < kThreadCount; ++i)
34     {
35         threads[i] = std::thread([&]() {
36             // Wait for all threads to start, so the following loop is as simultaneously executed as
37             // possible.
38             {
39                 std::unique_lock<std::mutex> lock(mutex);
40                 ++readyCount;
41                 if (readyCount < kThreadCount)
42                 {
43                     condVar.wait(lock, [&]() { return readyCount == kThreadCount; });
44                 }
45                 else
46                 {
47                     condVar.notify_all();
48                 }
49             }
50             for (size_t j = 0; j < kIterationCount; ++j)
51             {
52                 std::lock_guard<TestMutex> lock(testMutex);
53                 const int local    = testVar.load(std::memory_order_relaxed);
54                 const int newValue = local + 1;
55                 testVar.store(newValue, std::memory_order_relaxed);
56             }
57         });
58     }
59 
60     for (size_t i = 0; i < kThreadCount; ++i)
61     {
62         threads[i].join();
63     }
64 
65     const bool passed = testVar.load() == kThreadCount * kIterationCount;
66     return passed;
67 }
68 }  // anonymous namespace
69 
70 // Tests basic usage of std::mutex.
TEST(MutexTest,BasicStdMutex)71 TEST(MutexTest, BasicStdMutex)
72 {
73     EXPECT_TRUE(runBasicMutexTest<std::mutex>());
74 }
75 
76 // Tests basic usage of angle::SimpleMutex.
TEST(MutexTest,BasicSimpleMutex)77 TEST(MutexTest, BasicSimpleMutex)
78 {
79     EXPECT_TRUE(runBasicMutexTest<SimpleMutex>());
80 }
81 
82 // Tests failure with NoOpMutex.  Disabled because it can and will flake.
TEST(MutexTest,DISABLED_BasicNoOpMutex)83 TEST(MutexTest, DISABLED_BasicNoOpMutex)
84 {
85     // Technically not _guaranteed_ to calculate the wrong value, but highly likely to do so.
86     EXPECT_FALSE(runBasicMutexTest<NoOpMutex>());
87 }
88 }  // namespace angle
89