summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm18/include/llvm/Support/PerThreadBumpPtrAllocator.h
blob: 75620d7ff78bc4bf65b4673d2b1d689d86fe54aa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===- PerThreadBumpPtrAllocator.h ------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H
#define LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H

#include "llvm/Support/Allocator.h"
#include "llvm/Support/Parallel.h"

namespace llvm {
namespace parallel {

/// PerThreadAllocator is used in conjunction with ThreadPoolExecutor to allow
/// per-thread allocations. It wraps a possibly thread-unsafe allocator,
/// e.g. BumpPtrAllocator. PerThreadAllocator must be used with only main thread
/// or threads created by ThreadPoolExecutor, as it utilizes getThreadIndex,
/// which is set by ThreadPoolExecutor. To work properly, ThreadPoolExecutor
/// should be initialized before PerThreadAllocator is created.
/// TODO: The same approach might be implemented for ThreadPool.

template <typename AllocatorTy>
class PerThreadAllocator
    : public AllocatorBase<PerThreadAllocator<AllocatorTy>> {
public:
  PerThreadAllocator()
      : NumOfAllocators(parallel::getThreadCount()),
        Allocators(std::make_unique<AllocatorTy[]>(NumOfAllocators)) {}

  /// \defgroup Methods which could be called asynchronously:
  ///
  /// @{

  using AllocatorBase<PerThreadAllocator<AllocatorTy>>::Allocate;

  using AllocatorBase<PerThreadAllocator<AllocatorTy>>::Deallocate;

  /// Allocate \a Size bytes of \a Alignment aligned memory.
  void *Allocate(size_t Size, size_t Alignment) {
    assert(getThreadIndex() < NumOfAllocators);
    return Allocators[getThreadIndex()].Allocate(Size, Alignment);
  }

  /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
  /// allocator.
  void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
    assert(getThreadIndex() < NumOfAllocators);
    return Allocators[getThreadIndex()].Deallocate(Ptr, Size, Alignment);
  }

  /// Return allocator corresponding to the current thread.
  AllocatorTy &getThreadLocalAllocator() {
    assert(getThreadIndex() < NumOfAllocators);
    return Allocators[getThreadIndex()];
  }

  // Return number of used allocators.
  size_t getNumberOfAllocators() const { return NumOfAllocators; }
  /// @}

  /// \defgroup Methods which could not be called asynchronously:
  ///
  /// @{

  /// Reset state of allocators.
  void Reset() {
    for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
      Allocators[Idx].Reset();
  }

  /// Return total memory size used by all allocators.
  size_t getTotalMemory() const {
    size_t TotalMemory = 0;

    for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
      TotalMemory += Allocators[Idx].getTotalMemory();

    return TotalMemory;
  }

  /// Return allocated size by all allocators.
  size_t getBytesAllocated() const {
    size_t BytesAllocated = 0;

    for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
      BytesAllocated += Allocators[Idx].getBytesAllocated();

    return BytesAllocated;
  }

  /// Set red zone for all allocators.
  void setRedZoneSize(size_t NewSize) {
    for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++)
      Allocators[Idx].setRedZoneSize(NewSize);
  }

  /// Print statistic for each allocator.
  void PrintStats() const {
    for (size_t Idx = 0; Idx < getNumberOfAllocators(); Idx++) {
      errs() << "\n Allocator " << Idx << "\n";
      Allocators[Idx].PrintStats();
    }
  }
  /// @}

protected:
  size_t NumOfAllocators;
  std::unique_ptr<AllocatorTy[]> Allocators;
};

using PerThreadBumpPtrAllocator = PerThreadAllocator<BumpPtrAllocator>;

} // end namespace parallel
} // end namespace llvm

#endif // LLVM_SUPPORT_PERTHREADBUMPPTRALLOCATOR_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif