1//===- PerThreadBumpPtrAllocator.h ------------------------------*- C++ -*-===//
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#ifndef LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H
10#define LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H
11
12#include "llvm/Support/Allocator.h"
13#include "llvm/Support/Parallel.h"
14
15namespace llvm {
16namespace parallel {
17
18/// PerThreadAllocator is used in conjunction with ThreadPoolExecutor to allow
19/// per-thread allocations. It wraps a possibly thread-unsafe allocator,
20/// e.g. BumpPtrAllocator. PerThreadAllocator must be used with only main thread
21/// or threads created by ThreadPoolExecutor, as it utilizes getThreadIndex,
22/// which is set by ThreadPoolExecutor. To work properly, ThreadPoolExecutor
23/// should be initialized before PerThreadAllocator is created.
24/// TODO: The same approach might be implemented for ThreadPool.
25
26template <typename AllocatorTy>
27class PerThreadAllocator
28 : public AllocatorBase<PerThreadAllocator<AllocatorTy>> {
29public:
30 PerThreadAllocator()
31 : NumOfAllocators(parallel::getThreadCount()),
32 Allocators(std::make_unique<AllocatorTy[]>(NumOfAllocators)) {}
33
34 /// \defgroup Methods which could be called asynchronously:
35 ///
36 /// @{
37
38 using AllocatorBase<PerThreadAllocator<AllocatorTy>>::Allocate;
39
40 using AllocatorBase<PerThreadAllocator<AllocatorTy>>::Deallocate;
41
42 /// Allocate \a Size bytes of \a Alignment aligned memory.
43 void *Allocate(size_t Size, size_t Alignment) {
44 assert(getThreadIndex() < NumOfAllocators);
45 return Allocators[getThreadIndex()].Allocate(Size, Alignment);
46 }
47
48 /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
49 /// allocator.
50 void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
51 assert(getThreadIndex() < NumOfAllocators);
52 return Allocators[getThreadIndex()].Deallocate(Ptr, Size, Alignment);
53 }
54
55 /// Return allocator corresponding to the current thread.
56 AllocatorTy &getThreadLocalAllocator() {
57 assert(getThreadIndex() < NumOfAllocators);
58 return Allocators[getThreadIndex()];
59 }
60
61 // Return number of used allocators.
62 size_t getNumberOfAllocators() const { return NumOfAllocators; }
63 /// @}
64
65 /// \defgroup Methods which could not be called asynchronously:
66 ///
67 /// @{
68
69 /// Reset state of allocators.
70 void Reset() {
71 for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
72 Allocators[Idx].Reset();
73 }
74
75 /// Return total memory size used by all allocators.
76 size_t getTotalMemory() const {
77 size_t TotalMemory = 0;
78
79 for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
80 TotalMemory += Allocators[Idx].getTotalMemory();
81
82 return TotalMemory;
83 }
84
85 /// Return allocated size by all allocators.
86 size_t getBytesAllocated() const {
87 size_t BytesAllocated = 0;
88
89 for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
90 BytesAllocated += Allocators[Idx].getBytesAllocated();
91
92 return BytesAllocated;
93 }
94
95 /// Set red zone for all allocators.
96 void setRedZoneSize(size_t NewSize) {
97 for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
98 Allocators[Idx].setRedZoneSize(NewSize);
99 }
100
101 /// Print statistic for each allocator.
102 void PrintStats() const {
103 for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++) {
104 errs() << "\n Allocator " << Idx << "\n";
105 Allocators[Idx].PrintStats();
106 }
107 }
108 /// @}
109
110protected:
111 size_t NumOfAllocators;
112 std::unique_ptr<AllocatorTy[]> Allocators;
113};
114
115using PerThreadBumpPtrAllocator = PerThreadAllocator<BumpPtrAllocator>;
116
117} // end namespace parallel
118} // end namespace llvm
119
120#endif // LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H
121

source code of llvm/include/llvm/Support/PerThreadBumpPtrAllocator.h