#ifndef ELFSPY_PROFILER_H #define ELFSPY_PROFILER_H #include #include "elfspy/Capture.h" namespace spy { /** * @namespace spy * @class Profiler */ template class Profiler : public Capture { public: Profiler(H& hook); Profiler(const Profiler&) = delete; Profiler& operator=(const Profiler&) = delete; Profiler(Profiler&& move) = default; Profiler& operator=(Profiler& move) = default; ~Profiler(); private: static ReturnType profile(ArgTypes...); static ReturnType (*func_)(ArgTypes...); static Profiler* instance_; struct Recorder; friend class Recorder; inline void add(unsigned long long nanoseconds) { this->captures_.push_back(nanoseconds); } struct Recorder { inline Recorder() { clock_gettime(CLOCK_REALTIME, &start_); } inline ~Recorder() { struct timespec finish; clock_gettime(CLOCK_REALTIME, &finish); unsigned long long nanoseconds = 1000000000ULL * (finish.tv_sec - start_.tv_sec) + finish.tv_nsec - start_.tv_nsec; Profiler::instance_->add(nanoseconds); } struct timespec start_; }; H& hook_; }; template Profiler* Profiler::instance_ = nullptr; template ReturnType (*Profiler::func_)(ArgTypes...) = nullptr; template inline Profiler:: Profiler(H& hook) :hook_(hook) { func_ = hook_.patch(&Profiler::profile); instance_ = this; } template inline Profiler::~Profiler() { hook_.patch(func_); instance_ = nullptr; } template ReturnType Profiler::profile(ArgTypes... args) { Recorder r; return (*func_)(std::forward(args)...); } template inline auto profiler(H& hook) -> typename H::template Export::Type { return hook; } template inline auto new_profiler(H& hook) -> typename H::template Export::Type* { using Install = typename H::template Export::Type; return new Install(hook); } } // namespace elfspy #endif