1//===- LazyAtomicPointerTest.cpp ------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/LazyAtomicPointer.h"
10#include "llvm/Config/llvm-config.h"
11#include "llvm/Support/ThreadPool.h"
12#include "gtest/gtest.h"
13
14using namespace llvm;
15
16namespace {
17
18TEST(LazyAtomicPointer, loadOrGenerate) {
19 int Value = 0;
20 LazyAtomicPointer<int> Ptr;
21 DefaultThreadPool Threads;
22 for (unsigned I = 0; I < 4; ++I)
23 Threads.async(F: [&]() {
24 Ptr.loadOrGenerate(Generator: [&]() {
25 // Make sure this is only called once.
26 static std::atomic<bool> Once(false);
27 bool Current = false;
28 EXPECT_TRUE(Once.compare_exchange_strong(Current, true));
29 return &Value;
30 });
31 });
32
33 Threads.wait();
34 EXPECT_EQ(Ptr.load(), &Value);
35}
36
37#if (LLVM_ENABLE_THREADS)
38TEST(LazyAtomicPointer, BusyState) {
39 int Value = 0;
40 LazyAtomicPointer<int> Ptr;
41 DefaultThreadPool Threads;
42
43 std::mutex BusyLock, EndLock;
44 std::condition_variable Busy, End;
45 bool IsBusy = false, IsEnd = false;
46 Threads.async(F: [&]() {
47 Ptr.loadOrGenerate(Generator: [&]() {
48 // Notify busy state.
49 {
50 std::lock_guard<std::mutex> Lock(BusyLock);
51 IsBusy = true;
52 }
53 Busy.notify_all();
54 std::unique_lock<std::mutex> LEnd(EndLock);
55 // Wait for end state.
56 End.wait(lock&: LEnd, p: [&]() { return IsEnd; });
57 return &Value;
58 });
59 });
60
61 // Wait for busy state.
62 std::unique_lock<std::mutex> LBusy(BusyLock);
63 Busy.wait(lock&: LBusy, p: [&]() { return IsBusy; });
64 int *ExistingValue = nullptr;
65 // Busy state will not exchange the value.
66 EXPECT_FALSE(Ptr.compare_exchange_weak(ExistingValue, nullptr));
67 // Busy state return nullptr on load/compare_exchange_weak.
68 EXPECT_EQ(ExistingValue, nullptr);
69 EXPECT_EQ(Ptr.load(), nullptr);
70
71 // End busy state.
72 {
73 std::lock_guard<std::mutex> Lock(EndLock);
74 IsEnd = true;
75 }
76 End.notify_all();
77 Threads.wait();
78 EXPECT_EQ(Ptr.load(), &Value);
79}
80#endif
81
82} // namespace
83

source code of llvm/unittests/ADT/LazyAtomicPointerTest.cpp