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