File indexing completed on 2024-06-13 03:23:56
0001 #ifndef PerfTools_AllocMonitor_AllocMonitorRegistry_h
0002 #define PerfTools_AllocMonitor_AllocMonitorRegistry_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <memory>
0023 #include <vector>
0024 #include <malloc.h>
0025 #include <stdlib.h>
0026
0027
0028 #include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h"
0029
0030
0031
0032 namespace cms::perftools {
0033 class AllocTester;
0034
0035 class AllocMonitorRegistry {
0036 public:
0037 ~AllocMonitorRegistry();
0038
0039 AllocMonitorRegistry(AllocMonitorRegistry&&) = delete;
0040 AllocMonitorRegistry(const AllocMonitorRegistry&) = delete;
0041 AllocMonitorRegistry& operator=(const AllocMonitorRegistry&) = delete;
0042 AllocMonitorRegistry& operator=(AllocMonitorRegistry&&) = delete;
0043
0044
0045 static AllocMonitorRegistry& instance();
0046 static bool necessaryLibraryWasPreloaded();
0047
0048
0049
0050
0051 template <typename T, typename... ARGS>
0052 T* createAndRegisterMonitor(ARGS&&... iArgs);
0053 void deregisterMonitor(AllocMonitorBase*);
0054
0055 private:
0056 friend void* ::malloc(size_t) noexcept;
0057 friend void* ::calloc(size_t, size_t) noexcept;
0058 friend void* ::realloc(void*, size_t) noexcept;
0059 friend void* ::aligned_alloc(size_t, size_t) noexcept;
0060 friend int ::posix_memalign(void**, size_t, size_t) noexcept;
0061 friend void* ::memalign(size_t, size_t) noexcept;
0062 friend void ::free(void*) noexcept;
0063
0064 friend void* ::operator new(std::size_t size);
0065 friend void* ::operator new[](std::size_t size);
0066 friend void* ::operator new(std::size_t count, std::align_val_t al);
0067 friend void* ::operator new[](std::size_t count, std::align_val_t al);
0068 friend void* ::operator new(std::size_t count, const std::nothrow_t & tag) noexcept;
0069 friend void* ::operator new[](std::size_t count, const std::nothrow_t & tag) noexcept;
0070 friend void* ::operator new(std::size_t count, std::align_val_t al, const std::nothrow_t&) noexcept;
0071 friend void* ::operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t&) noexcept;
0072
0073 friend void ::operator delete(void* ptr) noexcept;
0074 friend void ::operator delete[](void* ptr) noexcept;
0075 friend void ::operator delete(void* ptr, std::align_val_t al) noexcept;
0076 friend void ::operator delete[](void* ptr, std::align_val_t al) noexcept;
0077 friend void ::operator delete(void* ptr, std::size_t sz) noexcept;
0078 friend void ::operator delete[](void* ptr, std::size_t sz) noexcept;
0079 friend void ::operator delete(void* ptr, std::size_t sz, std::align_val_t al) noexcept;
0080 friend void ::operator delete[](void* ptr, std::size_t sz, std::align_val_t al) noexcept;
0081 friend void ::operator delete(void* ptr, const std::nothrow_t & tag) noexcept;
0082 friend void ::operator delete[](void* ptr, const std::nothrow_t & tag) noexcept;
0083 friend void ::operator delete(void* ptr, std::align_val_t al, const std::nothrow_t & tag) noexcept;
0084 friend void ::operator delete[](void* ptr, std::align_val_t al, const std::nothrow_t & tag) noexcept;
0085
0086 friend class AllocTester;
0087
0088
0089 void start();
0090 bool stopReporting();
0091 void startReporting();
0092
0093 struct Guard {
0094 explicit Guard(AllocMonitorRegistry& iReg) noexcept : reg_(iReg), original_(iReg.stopReporting()) {}
0095 ~Guard() {
0096 if (original_) {
0097 reg_.startReporting();
0098 }
0099 }
0100
0101 bool shouldReport() const noexcept { return original_; }
0102
0103 Guard(Guard const&) = delete;
0104 Guard(Guard&&) = delete;
0105 Guard& operator=(Guard const&) = delete;
0106 Guard& operator=(Guard&&) = delete;
0107
0108 private:
0109 AllocMonitorRegistry& reg_;
0110 bool original_;
0111 };
0112
0113 Guard makeGuard() { return Guard(*this); }
0114
0115 void allocCalled_(size_t, size_t);
0116 void deallocCalled_(size_t);
0117
0118 template <typename ALLOC, typename ACT>
0119 auto allocCalled(size_t iRequested, ALLOC iAlloc, ACT iGetActual) {
0120 [[maybe_unused]] Guard g = makeGuard();
0121 auto a = iAlloc();
0122 if (g.shouldReport()) {
0123 allocCalled_(iRequested, iGetActual(a));
0124 }
0125 return a;
0126 }
0127 template <typename DEALLOC, typename ACT>
0128 void deallocCalled(void* iPtr, DEALLOC iDealloc, ACT iGetActual) {
0129 [[maybe_unused]] Guard g = makeGuard();
0130 if (g.shouldReport() and iPtr != nullptr) {
0131 deallocCalled_(iGetActual(iPtr));
0132 }
0133 iDealloc(iPtr);
0134 }
0135
0136 AllocMonitorRegistry();
0137 std::vector<std::unique_ptr<AllocMonitorBase>> monitors_;
0138 };
0139
0140 template <typename T, typename... ARGS>
0141 T* AllocMonitorRegistry::createAndRegisterMonitor(ARGS&&... iArgs) {
0142 [[maybe_unused]] Guard guard = makeGuard();
0143 start();
0144
0145 auto m = std::make_unique<T>(std::forward<ARGS>(iArgs)...);
0146 auto p = m.get();
0147 monitors_.push_back(std::move(m));
0148 return p;
0149 }
0150 }
0151 #endif