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 | |
15 | namespace llvm { |
16 | namespace 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 | |
26 | template <typename AllocatorTy> |
27 | class PerThreadAllocator |
28 | : public AllocatorBase<PerThreadAllocator<AllocatorTy>> { |
29 | public: |
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 | |
110 | protected: |
111 | size_t NumOfAllocators; |
112 | std::unique_ptr<AllocatorTy[]> Allocators; |
113 | }; |
114 | |
115 | using PerThreadBumpPtrAllocator = PerThreadAllocator<BumpPtrAllocator>; |
116 | |
117 | } // end namespace parallel |
118 | } // end namespace llvm |
119 | |
120 | #endif // LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H |
121 | |