1 //===- llvm/unittest/Support/ThreadSafeAllocatorTest.cpp ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/ThreadSafeAllocator.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/Support/ThreadPool.h"
12 #include "gtest/gtest.h"
20 struct AllocCondition
{
21 std::mutex BusyLock
, EndLock
;
22 std::condition_variable Busy
, End
;
23 bool IsBusy
= false, IsEnd
= false;
24 std::atomic
<unsigned> BytesAllocated
= 0;
26 void startAllocation() {
28 std::lock_guard
<std::mutex
> Lock(BusyLock
);
33 void waitAllocationStarted() {
34 std::unique_lock
<std::mutex
> LBusy(BusyLock
);
35 Busy
.wait(LBusy
, [&]() { return IsBusy
; });
38 void finishAllocation() {
40 std::lock_guard
<std::mutex
> Lock(EndLock
);
45 void waitAllocationFinished() {
46 std::unique_lock
<std::mutex
> LEnd(EndLock
);
47 // Wait for end state.
48 End
.wait(LEnd
, [&]() { return IsEnd
; });
53 class MockAllocator
: public AllocatorBase
<MockAllocator
> {
55 MockAllocator() = default;
57 void *Allocate(size_t Size
, size_t Alignment
) {
59 C
.waitAllocationFinished();
60 C
.BytesAllocated
+= Size
;
64 AllocCondition
&getAllocCondition() { return C
; }
73 #if (LLVM_ENABLE_THREADS)
74 TEST(ThreadSafeAllocatorTest
, AllocWait
) {
75 ThreadSafeAllocator
<MockAllocator
> Alloc
;
77 // Get the allocation from the allocator first since this requires a lock.
79 [&](MockAllocator
&Alloc
) { C
= &Alloc
.getAllocCondition(); });
80 DefaultThreadPool Threads
;
81 // First allocation of 1 byte.
82 Threads
.async([&Alloc
]() {
83 char *P
= (char *)Alloc
.Allocate(1, alignof(char));
87 EXPECT_EQ(C
->BytesAllocated
, 0u);
88 C
->waitAllocationStarted(); // wait till 1st alloocation starts.
89 // Second allocation of 2 bytes.
90 Threads
.async([&Alloc
]() {
91 char *P
= (char *)Alloc
.Allocate(2, alignof(char));
94 C
->finishAllocation(); // finish 1st allocation.
96 C
->waitAllocationStarted(); // wait till 2nd allocation starts.
97 // still 1 byte allocated since 2nd allocation is not finished yet.
98 EXPECT_EQ(C
->BytesAllocated
, 1u);
99 C
->finishAllocation(); // finish 2nd allocation.
101 Threads
.wait(); // all allocations done.
102 EXPECT_EQ(C
->BytesAllocated
, 3u);
105 TEST(ThreadSafeAllocatorTest
, AllocWithAlign
) {
106 ThreadSafeAllocator
<BumpPtrAllocator
> Alloc
;
107 DefaultThreadPool Threads
;
109 for (unsigned Index
= 1; Index
< 100; ++Index
)
111 [&Alloc
](unsigned I
) {
112 int *P
= (int *)Alloc
.Allocate(sizeof(int) * I
, alignof(int));
119 Alloc
.applyLocked([](BumpPtrAllocator
&Alloc
) {
120 EXPECT_EQ(4950U * sizeof(int), Alloc
.getBytesAllocated());
124 TEST(ThreadSafeAllocatorTest
, SpecificBumpPtrAllocator
) {
125 ThreadSafeAllocator
<SpecificBumpPtrAllocator
<int>> Alloc
;
126 DefaultThreadPool Threads
;
128 for (unsigned Index
= 1; Index
< 100; ++Index
)
130 [&Alloc
](unsigned I
) {
131 int *P
= Alloc
.Allocate(I
);