CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
152 lines
3.6 KiB
C++
152 lines
3.6 KiB
C++
//===- LockedAccessTest.cpp -----------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Tests for orc-rt's LockedAccess.h APIs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "orc-rt/LockedAccess.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <mutex>
|
|
#include <thread>
|
|
#include <type_traits>
|
|
|
|
using namespace orc_rt;
|
|
|
|
namespace {
|
|
|
|
template <typename T> struct Foo {
|
|
std::mutex M;
|
|
T Val{};
|
|
|
|
Foo() = default;
|
|
Foo(T Val) : Val(std::move(Val)) {}
|
|
|
|
auto get() { return LockedAccess(Val, M); }
|
|
|
|
auto getConst() { return LockedAccess(std::as_const(Val), M); }
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
TEST(LockedAccessTest, ArrowRead) {
|
|
Foo<std::pair<int, int>> F({42, 7});
|
|
EXPECT_EQ(F.get()->first, 42);
|
|
EXPECT_EQ(F.get()->second, 7);
|
|
}
|
|
|
|
TEST(LockedAccessTest, ArrowWrite) {
|
|
Foo<std::pair<int, int>> F;
|
|
F.get()->first = 10;
|
|
F.get()->second = 20;
|
|
EXPECT_EQ(F.Val.first, 10);
|
|
EXPECT_EQ(F.Val.second, 20);
|
|
}
|
|
|
|
TEST(LockedAccessTest, ConstArrowReturnsConstPtr) {
|
|
Foo<int> F(42);
|
|
static_assert(std::is_const_v<
|
|
std::remove_pointer_t<decltype(F.getConst().operator->())>>,
|
|
"const overload should return const pointer");
|
|
}
|
|
|
|
TEST(LockedAccessTest, DerefRead) {
|
|
Foo<int> F(42);
|
|
EXPECT_EQ(*F.get(), 42);
|
|
}
|
|
|
|
TEST(LockedAccessTest, DerefWrite) {
|
|
Foo<int> F;
|
|
*F.get() = 7;
|
|
EXPECT_EQ(F.Val, 7);
|
|
}
|
|
|
|
TEST(LockedAccessTest, DerefPassToFunction) {
|
|
Foo<int> F(42);
|
|
auto timesTwo = [](int &X) { return X * 2; };
|
|
EXPECT_EQ(timesTwo(*F.get()), 84);
|
|
}
|
|
|
|
TEST(LockedAccessTest, ConstDerefReturnsConstRef) {
|
|
Foo<int> F(42);
|
|
static_assert(
|
|
std::is_const_v<std::remove_reference_t<decltype(*F.getConst())>>,
|
|
"const overload should return const reference");
|
|
}
|
|
|
|
TEST(LockedAccessTest, WithRefRead) {
|
|
Foo<int> F(42);
|
|
F.get().with_ref([](int &Y) { EXPECT_EQ(Y, 42); });
|
|
}
|
|
|
|
TEST(LockedAccessTest, WithRefWrite) {
|
|
Foo<int> F;
|
|
F.get().with_ref([](int &Y) { Y = 7; });
|
|
EXPECT_EQ(F.Val, 7);
|
|
}
|
|
|
|
TEST(LockedAccessTest, WithRefReturnValue) {
|
|
Foo<int> F(42);
|
|
int Result = F.get().with_ref([](int &Y) { return Y + 1; });
|
|
EXPECT_EQ(Result, 43);
|
|
}
|
|
|
|
TEST(LockedAccessTest, WithRefReturnReference) {
|
|
Foo<std::pair<int, int>> F({1, 2});
|
|
int &Ref = F.get().with_ref(
|
|
[](std::pair<int, int> &P) -> int & { return P.second; });
|
|
EXPECT_EQ(&Ref, &F.Val.second);
|
|
}
|
|
|
|
TEST(LockedAccessTest, ConstWithRefGetsConstReference) {
|
|
Foo<int> F(42);
|
|
F.getConst().with_ref([](const int &Y) { EXPECT_EQ(Y, 42); });
|
|
}
|
|
|
|
TEST(LockedAccessTest, WithRefMultiStatement) {
|
|
Foo<std::pair<int, int>> F;
|
|
F.get().with_ref([](std::pair<int, int> &P) {
|
|
P.first = 10;
|
|
P.second = P.first + 5;
|
|
});
|
|
EXPECT_EQ(F.Val.first, 10);
|
|
EXPECT_EQ(F.Val.second, 15);
|
|
}
|
|
|
|
TEST(LockedAccessTest, HoldsLockDuringArrow) {
|
|
struct Checker {
|
|
Foo<Checker> *F;
|
|
bool isLocked() { return !F->M.try_lock(); }
|
|
};
|
|
Foo<Checker> F({&F});
|
|
EXPECT_TRUE(F.get()->isLocked());
|
|
}
|
|
|
|
TEST(LockedAccessTest, HoldsLockDuringWithRef) {
|
|
Foo<int> F;
|
|
EXPECT_TRUE(F.get().with_ref([&](int &) { return !F.M.try_lock(); }));
|
|
}
|
|
|
|
TEST(LockedAccessTest, ProtectsAcrossThreads) {
|
|
Foo<int> F;
|
|
const int Iters = 10000;
|
|
|
|
auto Increment = [&]() {
|
|
for (int I = 0; I < Iters; ++I)
|
|
F.get().with_ref([](int &C) { ++C; });
|
|
};
|
|
|
|
std::thread T1(Increment);
|
|
std::thread T2(Increment);
|
|
T1.join();
|
|
T2.join();
|
|
|
|
EXPECT_EQ(F.Val, 2 * Iters);
|
|
}
|