83 lines · cpp
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-exception6//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([&]() {24 Ptr.loadOrGenerate([&]() {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([&]() {47 Ptr.loadOrGenerate([&]() {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(LEnd, [&]() { return IsEnd; });57 return &Value;58 });59 });60 61 // Wait for busy state.62 std::unique_lock<std::mutex> LBusy(BusyLock);63 Busy.wait(LBusy, [&]() { 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#endif81 82} // namespace83