timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
tim::sampling::sampler< CompT< Types... >, N, SigIds... > Struct Template Reference

#include "timemory/sampling/sampler.hpp"

+ Collaboration diagram for tim::sampling::sampler< CompT< Types... >, N, SigIds... >:

Public Types

using this_type = sampler< CompT< Types... >, N, SigIds... >
 
using base_type = component::base< this_type, void >
 
using components_t = CompT< Types... >
 
using signal_set_t = std::set< int >
 
using pid_cb_t = std::function< bool(pid_t, int, int)>
 
using array_t = conditional_t< fixed_size_t< N >::value, std::array< components_t, N >, std::vector< components_t > >
 
using array_type = array_t
 
using tracker_type = policy::instance_tracker< this_type, false >
 
using storage_type = empty_storage
 

Public Member Functions

template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
 sampler (const std::string &_label, signal_set_t _good, signal_set_t _bad=signal_set_t{})
 
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
 sampler (const std::string &_label, signal_set_t _good, signal_set_t _bad=signal_set_t{})
 
 ~sampler ()
 
template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
void sample ()
 
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
void sample ()
 
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t< Tp::value > = 0>
void start ()
 
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t< Tp::value > = 0>
void stop ()
 
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value > = 0>
void start ()
 
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value > = 0>
void stop ()
 
bool is_good (int v) const
 
bool is_bad (int v) const
 
auto good_count () const
 
auto bad_count () const
 
auto count () const
 
auto & get_good ()
 
auto & get_bad ()
 
const auto & get_good () const
 
const auto & get_bad () const
 
auto backtrace_enabled () const
 
void enable_backtrace (bool val)
 
components_t *& get_last ()
 
components_tget_last () const
 
components_t *& get_latest ()
 
components_tget_latest () const
 
template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
components_tget (size_t idx)
 
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
components_tget (size_t idx)
 
template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
const components_tget (size_t idx) const
 
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
const components_tget (size_t idx) const
 
array_tget_data ()
 
const array_tget_data () const
 
template<typename Tp , enable_if_t< Tp::value > >
sampler< CompT< Types... >, N, SigIds... >::components_tget (size_t idx)
 
template<typename Tp , enable_if_t< Tp::value > >
const sampler< CompT< Types... >, N, SigIds... >::components_tget (size_t idx) const
 
void get () const
 

Static Public Member Functions

static void execute (int signum)
 
static void execute (int signum, siginfo_t *, void *)
 
static auto & get_samplers ()
 
static auto get_latest_samples ()
 
static void configure (std::set< int > _signals, int _verbose=1)
 Set up the sampler. More...
 
static void configure (int _signal=SIGALRM, int _verbose=1)
 
static void ignore (const std::set< int > &_signals)
 Ignore the signals. More...
 
static void clear ()
 Clear all signals. Recommended to call ignore() prior to clearing all the signals. More...
 
static void pause ()
 Pause until a signal is delivered. More...
 
template<typename Func = pid_cb_t>
static int wait (pid_t _pid, int _verbose, bool _debug, Func &&_callback=pid_callback())
 Wait function with an optional user callback of type: More...
 
template<typename Func = pid_cb_t>
static int wait (int _verbose=settings::verbose(), bool _debug=settings::debug(), Func &&_callback=pid_callback())
 
template<typename Func , enable_if_t< std::is_function< Func >::value > = 0>
static int wait (pid_t _pid, Func &&_callback, int _verbose=settings::verbose(), bool _debug=settings::debug())
 
template<typename Func , enable_if_t< std::is_function< Func >::value > = 0>
static int wait (Func &&_callback, int _verbose=settings::verbose(), bool _debug=settings::debug())
 
static void set_flags (int _flags)
 Set the sigaction flags, e.g. SA_RESTART | SA_SIGINFO. More...
 
static void set_delay (double fdelay)
 Value, expressed in seconds, that sets the length of time the sampler waits before starting sampling of the relevant measurements. More...
 
static void set_frequency (double ffreq)
 
static void set_rate (double frate)
 Value, expressed in number of interupts per second, that configures the frequency that the sampler samples the relevant measurements. More...
 
static int64_t get_delay (int64_t units=units::usec)
 Get the delay of the sampler. More...
 
static int64_t get_frequency (int64_t units=units::usec)
 Get the frequency of the sampler. More...
 
static int get_itimer (int _signal)
 Returns the itimer value associated with the given signal. More...
 
static bool check_itimer (int _stat, bool _throw_exception=false)
 Checks to see if there was an error setting or getting itimer val. More...
 
template<typename... Args>
static opaque get_opaque (Args &&...)
 

Protected Attributes

bool m_backtrace = false
 
size_t m_idx = 0
 
components_tm_last = nullptr
 
signal_set_t m_good = {}
 
signal_set_t m_bad = {}
 
array_t m_data = {}
 

Detailed Description

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
struct tim::sampling::sampler< CompT< Types... >, N, SigIds... >

Definition at line 157 of file sampler.hpp.

Member Typedef Documentation

◆ array_t

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::array_t = conditional_t<fixed_size_t<N>::value, std::array<components_t, N>, std::vector<components_t> >

Definition at line 166 of file sampler.hpp.

◆ array_type

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::array_type = array_t

Definition at line 169 of file sampler.hpp.

◆ base_type

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::base_type = component::base<this_type, void>

Definition at line 162 of file sampler.hpp.

◆ components_t

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::components_t = CompT<Types...>

Definition at line 163 of file sampler.hpp.

◆ pid_cb_t

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::pid_cb_t = std::function<bool(pid_t, int, int)>

Definition at line 165 of file sampler.hpp.

◆ signal_set_t

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::signal_set_t = std::set<int>

Definition at line 164 of file sampler.hpp.

◆ storage_type

using tim::component::empty_base::storage_type = empty_storage
inherited

Definition at line 66 of file declaration.hpp.

◆ this_type

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::this_type = sampler<CompT<Types...>, N, SigIds...>

Definition at line 161 of file sampler.hpp.

◆ tracker_type

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
using tim::sampling::sampler< CompT< Types... >, N, SigIds... >::tracker_type = policy::instance_tracker<this_type, false>

Definition at line 170 of file sampler.hpp.

Constructor & Destructor Documentation

◆ sampler() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
tim::sampling::sampler< CompT< Types... >, N, SigIds... >::sampler ( const std::string &  _label,
signal_set_t  _good,
signal_set_t  _bad = signal_set_t{} 
)

Definition at line 406 of file sampler.hpp.

408: m_last(nullptr)
409, m_good(std::move(_good))
410, m_bad(std::move(_bad))
411{
412 TIMEMORY_FOLD_EXPRESSION(m_good.insert(SigIds));
413 m_data.fill(components_t(_label));
414 m_last = &m_data.front();
415 auto_lock_t lk(type_mutex<this_type>());
416 get_samplers().push_back(this);
417}
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
Definition: locking.hpp:42
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56

References TIMEMORY_FOLD_EXPRESSION.

◆ sampler() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
tim::sampling::sampler< CompT< Types... >, N, SigIds... >::sampler ( const std::string &  _label,
signal_set_t  _good,
signal_set_t  _bad = signal_set_t{} 
)

◆ ~sampler()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
tim::sampling::sampler< CompT< Types... >, N, SigIds... >::~sampler

Definition at line 439 of file sampler.hpp.

440{
441 auto_lock_t lk(type_mutex<this_type>());
442 auto& _samplers = get_samplers();
443 auto itr = std::find(_samplers.begin(), _samplers.end(), this);
444 if(itr != _samplers.end())
445 _samplers.erase(itr);
446}

Member Function Documentation

◆ backtrace_enabled()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto tim::sampling::sampler< CompT< Types... >, N, SigIds... >::backtrace_enabled ( ) const
inline

Definition at line 218 of file sampler.hpp.

◆ bad_count()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto tim::sampling::sampler< CompT< Types... >, N, SigIds... >::bad_count ( ) const
inline

Definition at line 209 of file sampler.hpp.

209{ return m_bad.size(); }

◆ check_itimer()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
bool tim::sampling::sampler< CompT< Types... >, N, SigIds... >::check_itimer ( int  _stat,
bool  _throw_exception = false 
)
static

Checks to see if there was an error setting or getting itimer val.

Definition at line 1002 of file sampler.hpp.

1003{
1004 if(_stat == EFAULT)
1005 {
1006 auto msg =
1007 TIMEMORY_JOIN(" ", "Warning! setitimer returned EFAULT.",
1008 "Either the new itimerval or the old itimerval was invalid");
1009 if(_throw_exception)
1010 {
1012 }
1013 else
1014 {
1015 std::cerr << msg << '\n';
1016 }
1017 }
1018 else if(_stat == EINVAL)
1019 {
1020 auto msg = TIMEMORY_JOIN(" ", "Warning! setitimer returned EINVAL.",
1021 "Either the timer was not one of: ['ITIMER_REAL', "
1022 "'ITIMER_VIRTUAL', "
1023 "'ITIMER_PROF'] or the old itimerval was invalid");
1024 if(_throw_exception)
1025 {
1027 }
1028 else
1029 {
1030 std::cerr << msg << '\n';
1031 }
1032 }
1033 return (_stat != EFAULT && _stat != EINVAL);
1034}
#define TIMEMORY_EXCEPTION(...)
Definition: types.hpp:138
#define TIMEMORY_JOIN(delim,...)
Definition: macros.hpp:90

References TIMEMORY_EXCEPTION, and TIMEMORY_JOIN.

◆ clear()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::clear ( )
inlinestatic

Clear all signals. Recommended to call ignore() prior to clearing all the signals.

Definition at line 261 of file sampler.hpp.

261{ get_persistent_data().m_signals.clear(); }

◆ configure() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
static void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::configure ( int  _signal = SIGALRM,
int  _verbose = 1 
)
inlinestatic

Definition at line 247 of file sampler.hpp.

248 {
249 configure({ _signal }, _verbose);
250 }
static void configure(std::set< int > _signals, int _verbose=1)
Set up the sampler.
Definition: sampler.hpp:649

References tim::configure().

◆ configure() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::configure ( std::set< int >  _signals,
int  _verb = 1 
)
static

Set up the sampler.

Parameters
[in]_signalsA set of signals to catch
[in]_verbLogging Verbosity

Definition at line 649 of file sampler.hpp.

650{
651 // already active
652 if(get_persistent_data().m_active)
653 return;
654
655 size_t wait_count = 0;
656 {
657 auto_lock_t lk(type_mutex<this_type>());
658 for(auto& itr : get_samplers())
659 wait_count += itr->count();
660 }
661
662 if(wait_count == 0)
663 {
664 if(_verbose > 0)
665 {
666 fprintf(stderr,
667 "[sampler::configure]> No existing sampler has been configured to "
668 "sample at a specific signal or fail at a specific signal. itimer "
669 "for will not be set. Sampler will only wait for target pid to "
670 "exit\n");
671 }
672 _signals.clear();
673 }
674 else
675 {
676 TIMEMORY_FOLD_EXPRESSION(_signals.insert(SigIds));
677 }
678
679 if(!_signals.empty())
680 {
681 auto& _custom_sa = get_persistent_data().m_custom_sigaction;
682 auto& _custom_it = get_persistent_data().m_custom_itimerval;
683 auto& _original_sa = get_persistent_data().m_original_sigaction;
684 auto& _original_it = get_persistent_data().m_original_itimerval;
685
686 memset(&_custom_sa, 0, sizeof(_custom_sa));
687
688 _custom_sa.sa_handler = &this_type::execute;
689 _custom_sa.sa_sigaction = &this_type::execute;
690 _custom_sa.sa_flags = SA_RESTART | SA_SIGINFO;
691
692 // start the interval timer
693 for(const auto& itr : _signals)
694 {
695 // get the associated itimer type
696 auto _itimer = get_itimer(itr);
697 if(_itimer < 0)
698 {
700 TIMEMORY_JOIN(" ", "Error! Alarm cannot be set for signal", itr,
701 "because the signal does not map to a known itimer "
702 "value\n"));
703 }
704
705 // configure the sigaction
706 int _sret = sigaction(itr, &_custom_sa, &_original_sa);
707 if(_sret == 0)
708 {
709 get_persistent_data().m_signals.insert(itr);
710 }
711 else
712 {
714 " ", "Error! sigaction could not be set for signal", itr));
715 }
716
717 // start the alarm (throws if fails)
718 check_itimer(setitimer(_itimer, &_custom_it, &_original_it), true);
719 }
720 }
721
722 // if active field based on whether there are signals
723 get_persistent_data().m_active = !get_persistent_data().m_signals.empty();
724}
std::shared_ptr< DataType > execute(std::shared_ptr< DataType > _data=std::make_shared< DataType >())
static bool check_itimer(int _stat, bool _throw_exception=false)
Checks to see if there was an error setting or getting itimer val.
Definition: sampler.hpp:1002
static int get_itimer(int _signal)
Returns the itimer value associated with the given signal.
Definition: sampler.hpp:986

References tim::ert::execute(), TIMEMORY_EXCEPTION, TIMEMORY_FOLD_EXPRESSION, and TIMEMORY_JOIN.

◆ count()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto tim::sampling::sampler< CompT< Types... >, N, SigIds... >::count ( ) const
inline

◆ enable_backtrace()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::enable_backtrace ( bool  val)
inline

Definition at line 219 of file sampler.hpp.

219{ m_backtrace = val; }

◆ execute() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::execute ( int  signum)
static

Definition at line 589 of file sampler.hpp.

590{
591 if(settings::debug())
592 {
593 printf("[pid=%i][tid=%i][%s]> sampling...\n", (int) process::get_id(),
594 (int) threading::get_id(), demangle<this_type>().c_str());
595 }
596
597 for(auto& itr : get_samplers())
598 {
599 if(itr->is_good(signum))
600 {
601 itr->sample();
602 }
603 else if(itr->is_bad(signum))
604 {
605 char msg[1024];
606 sprintf(msg, "[timemory]> sampler instance caught bad signal: %i ...",
607 signum);
608 perror(msg);
609 signal(signum, SIG_DFL);
610 raise(signum);
611 }
612 }
613}

References tim::debug.

◆ execute() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::execute ( int  signum,
siginfo_t *  ,
void *   
)
static

Definition at line 619 of file sampler.hpp.

620{
621 if(settings::debug())
622 {
623 printf("[pid=%i][tid=%i][%s]> sampling...\n", (int) process::get_id(),
624 (int) threading::get_id(), demangle<this_type>().c_str());
625 }
626
627 for(auto& itr : get_samplers())
628 {
629 if(itr->is_good(signum))
630 {
631 itr->sample();
632 }
633 else if(itr->is_bad(signum))
634 {
635 char msg[1024];
636 sprintf(msg, "[timemory]> sampler instance caught bad signal: %i ...",
637 signum);
638 perror(msg);
639 signal(signum, SIG_DFL);
640 raise(signum);
641 }
642 }
643}

References tim::debug.

◆ get() [1/7]

void tim::component::empty_base::get ( ) const
inlineinherited

Definition at line 69 of file declaration.hpp.

69{}

◆ get() [2/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx)

◆ get() [3/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx)

◆ get() [4/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
sampler< CompT< Types... >, N, SigIds... >::components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx)

Definition at line 550 of file sampler.hpp.

551{
552 return m_data.at(idx % N);
553}

◆ get() [5/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t< Tp::value > = 0>
const components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx) const

◆ get() [6/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
const components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx) const

◆ get() [7/7]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
const sampler< CompT< Types... >, N, SigIds... >::components_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get ( size_t  idx) const

Definition at line 560 of file sampler.hpp.

561{
562 return m_data.at(idx % N);
563}

◆ get_bad() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_bad ( )
inline

Definition at line 213 of file sampler.hpp.

213{ return m_bad; }

◆ get_bad() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
const auto & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_bad ( ) const
inline

Definition at line 216 of file sampler.hpp.

216{ return m_bad; }

◆ get_data() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
array_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_data ( )
inline

Definition at line 237 of file sampler.hpp.

237{ return m_data; }

◆ get_data() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
const array_t & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_data ( ) const
inline

Definition at line 238 of file sampler.hpp.

238{ return m_data; }

◆ get_delay()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
int64_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_delay ( int64_t  units = units::usec)
inlinestatic

Get the delay of the sampler.

Definition at line 960 of file sampler.hpp.

961{
962 double _us = (get_persistent_data().m_custom_itimerval.it_value.tv_sec * 1000000) +
963 get_persistent_data().m_custom_itimerval.it_value.tv_usec;
964 _us *= units::usec;
965 _us /= units;
966 return std::max<int64_t>(_us, 1);
967}

◆ get_frequency()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
int64_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_frequency ( int64_t  units = units::usec)
inlinestatic

Get the frequency of the sampler.

Definition at line 973 of file sampler.hpp.

974{
975 double _us = (get_persistent_data().m_custom_itimerval.it_interval.tv_sec * 1000000) +
976 get_persistent_data().m_custom_itimerval.it_interval.tv_usec;
977 _us *= units::usec;
978 _us /= units;
979 return std::max<int64_t>(_us, 1);
980}

◆ get_good() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_good ( )
inline

Definition at line 212 of file sampler.hpp.

212{ return m_good; }

◆ get_good() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
const auto & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_good ( ) const
inline

Definition at line 215 of file sampler.hpp.

215{ return m_good; }

◆ get_itimer()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
int tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_itimer ( int  _signal)
static

Returns the itimer value associated with the given signal.

Definition at line 986 of file sampler.hpp.

987{
988 int _itimer = -1;
989 switch(_signal)
990 {
991 case SIGALRM: _itimer = ITIMER_REAL; break;
992 case SIGVTALRM: _itimer = ITIMER_VIRTUAL; break;
993 case SIGPROF: _itimer = ITIMER_PROF; break;
994 }
995 return _itimer;
996}

◆ get_last() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
components_t *& tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_last ( )
inline

Definition at line 221 of file sampler.hpp.

221{ return m_last; }

◆ get_last() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
components_t * tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_last ( ) const
inline

Definition at line 222 of file sampler.hpp.

222{ return m_last; }

◆ get_latest() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
components_t *& tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_latest ( )
inline

Definition at line 224 of file sampler.hpp.

224{ return m_last; }

◆ get_latest() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
components_t * tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_latest ( ) const
inline

Definition at line 225 of file sampler.hpp.

225{ return m_last; }

◆ get_latest_samples()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_latest_samples
inlinestatic

Definition at line 392 of file sampler.hpp.

393{
394 std::vector<components_t*> _last{};
395 auto_lock_t lk(type_mutex<this_type>());
396 _last.reserve(get_persistent_data().m_instances.size());
397 for(auto& itr : get_persistent_data().m_instances)
398 _last.emplace_back(itr->get_last());
399 return _last;
400}

◆ get_opaque()

template<typename... Args>
static opaque tim::component::empty_base::get_opaque ( Args &&  ...)
inlinestaticinherited

Definition at line 72 of file declaration.hpp.

73 {
74 return opaque{};
75 }

◆ get_samplers()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
static auto & tim::sampling::sampler< CompT< Types... >, N, SigIds... >::get_samplers ( )
inlinestatic

Definition at line 174 of file sampler.hpp.

174{ return get_persistent_data().m_instances; }

◆ good_count()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
auto tim::sampling::sampler< CompT< Types... >, N, SigIds... >::good_count ( ) const
inline

Definition at line 208 of file sampler.hpp.

208{ return m_good.size(); }

◆ ignore()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::ignore ( const std::set< int > &  _signals)
inlinestatic

Ignore the signals.

Parameters
[in]_signalsSet of signals

Definition at line 730 of file sampler.hpp.

731{
732 for(const auto& itr : _signals)
733 signal(itr, SIG_IGN);
734
735 auto& _original_it = get_persistent_data().m_original_itimerval;
736 for(const auto& itr : _signals)
737 {
738 itimerval_t _curr;
739 auto _itimer = get_itimer(itr);
740 if(_itimer < 0)
741 continue;
742 check_itimer(getitimer(_itimer, &_curr));
743 // stop the alarm
744 if(_curr.it_interval.tv_usec > 0 || _curr.it_interval.tv_sec > 0)
745 check_itimer(setitimer(_itimer, &_original_it, &_curr));
746 }
747
748 // if active field based on whether there are signals
749 get_persistent_data().m_active = !get_persistent_data().m_signals.empty();
750}

◆ is_bad()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
bool tim::sampling::sampler< CompT< Types... >, N, SigIds... >::is_bad ( int  v) const
inline

Definition at line 206 of file sampler.hpp.

206{ return m_bad.count(v) > 0; }

◆ is_good()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
bool tim::sampling::sampler< CompT< Types... >, N, SigIds... >::is_good ( int  v) const
inline

Definition at line 205 of file sampler.hpp.

205{ return m_good.count(v) > 0; }

◆ pause()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::pause ( )
inlinestatic

Pause until a signal is delivered.

Definition at line 265 of file sampler.hpp.

266 {
267 if(!get_persistent_data().m_signals.empty())
268 ::pause();
269 }
static void pause()
Pause until a signal is delivered.
Definition: sampler.hpp:265

◆ sample() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::sample

Definition at line 453 of file sampler.hpp.

454{
455 // if(!base_type::get_is_running())
456 // return;
457 m_last = &(m_data.at((m_idx++) % N));
458 // get last 4 of 7 backtrace entries (i.e. offset by 3)
459 if(m_backtrace)
460 {
461 m_last->sample(get_backtrace<4, 3>());
462 }
463 else
464 {
465 m_last->sample();
466 }
467}

◆ sample() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_size_t<N>, enable_if_t<!Tp::value > = 0>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::sample ( )

◆ set_delay()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::set_delay ( double  fdelay)
static

Value, expressed in seconds, that sets the length of time the sampler waits before starting sampling of the relevant measurements.

Definition at line 922 of file sampler.hpp.

923{
924 get_persistent_data().m_freq = fdelay;
925 int delay_sec = fdelay;
926 int delay_usec = static_cast<int>(fdelay * 1000000) % 1000000;
928 {
929 fprintf(stderr, "sampler delay : %i sec + %i usec\n", delay_sec,
930 delay_usec);
931 }
932 // Configure the timer to expire after designated delay...
933 get_persistent_data().m_custom_itimerval.it_value.tv_sec = delay_sec;
934 get_persistent_data().m_custom_itimerval.it_value.tv_usec = delay_usec;
935}

References tim::debug, and tim::verbose.

◆ set_flags()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::set_flags ( int  _flags)
inlinestatic

Set the sigaction flags, e.g. SA_RESTART | SA_SIGINFO.

Parameters
flags[in]the sigaction flags to use

Definition at line 315 of file sampler.hpp.

315{ get_persistent_data().m_flags = _flags; }

◆ set_frequency()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::set_frequency ( double  ffreq)
static

Definition at line 941 of file sampler.hpp.

942{
943 get_persistent_data().m_freq = ffreq;
944 int freq_sec = ffreq;
945 int freq_usec = static_cast<int>(ffreq * 1000000) % 1000000;
947 {
948 fprintf(stderr, "sampler frequency : %i sec + %i usec\n", freq_sec,
949 freq_usec);
950 }
951 // Configure the timer to expire after designated delay...
952 get_persistent_data().m_custom_itimerval.it_interval.tv_sec = freq_sec;
953 get_persistent_data().m_custom_itimerval.it_interval.tv_usec = freq_usec;
954}

References tim::debug, and tim::verbose.

◆ set_rate()

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::set_rate ( double  frate)
inlinestatic

Value, expressed in number of interupts per second, that configures the frequency that the sampler samples the relevant measurements.

Definition at line 330 of file sampler.hpp.

330{ set_frequency(1.0 / frate); }

◆ start() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::start

Definition at line 496 of file sampler.hpp.

497{
498 auto cnt = tracker_type::start();
499 base_type::set_started();
500 for(auto& itr : m_data)
501 itr.start();
502 if(cnt == 0)
503 configure({ SigIds... });
504}
void start(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:316

References tim::configure(), and tim::invoke::start().

◆ start() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value > = 0>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::start ( )

◆ stop() [1/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp , enable_if_t<!Tp::value > >
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::stop

Definition at line 511 of file sampler.hpp.

512{
513 auto cnt = tracker_type::stop();
514 base_type::set_stopped();
515 for(auto& itr : m_data)
516 itr.stop();
517 if(cnt == 0)
518 ignore({ SigIds... });
519}
void stop(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:386
static void ignore(const std::set< int > &_signals)
Ignore the signals.
Definition: sampler.hpp:730

References tim::invoke::stop().

◆ stop() [2/2]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Tp = fixed_sig_t<SigIds...>, enable_if_t<!Tp::value > = 0>
void tim::sampling::sampler< CompT< Types... >, N, SigIds... >::stop ( )

◆ wait() [1/4]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Func , enable_if_t< std::is_function< Func >::value > = 0>
static int tim::sampling::sampler< CompT< Types... >, N, SigIds... >::wait ( Func &&  _callback,
int  _verbose = settings::verbose(),
bool  _debug = settings::debug() 
)
inlinestatic

Definition at line 304 of file sampler.hpp.

306 {
307 return wait(process::get_target_id(), _verbose, _debug,
308 std::forward<Func>(_callback));
309 }
static int wait(pid_t _pid, int _verbose, bool _debug, Func &&_callback=pid_callback())
Wait function with an optional user callback of type:
Definition: sampler.hpp:757

◆ wait() [2/4]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Func = pid_cb_t>
static int tim::sampling::sampler< CompT< Types... >, N, SigIds... >::wait ( int  _verbose = settings::verbose(),
bool  _debug = settings::debug(),
Func &&  _callback = pid_callback() 
)
inlinestatic

Definition at line 289 of file sampler.hpp.

291 {
292 return wait(process::get_target_id(), _verbose, _debug,
293 std::forward<Func>(_callback));
294 }

◆ wait() [3/4]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Func , enable_if_t< std::is_function< Func >::value > = 0>
static int tim::sampling::sampler< CompT< Types... >, N, SigIds... >::wait ( pid_t  _pid,
Func &&  _callback,
int  _verbose = settings::verbose(),
bool  _debug = settings::debug() 
)
inlinestatic

Definition at line 297 of file sampler.hpp.

299 {
300 return wait(_pid, _verbose, _debug, std::forward<Func>(_callback));
301 }

◆ wait() [4/4]

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
template<typename Func >
int tim::sampling::sampler< CompT< Types... >, N, SigIds... >::wait ( pid_t  _pid,
int  _verb,
bool  _debug,
Func &&  _cb = pid_callback() 
)
static

Wait function with an optional user callback of type:

Parameters
[in]_pidProcess id to wait on
[in]_verbLogging verbosity
[in]_debugEnable debug logging
[in]_cbCallback for checking whether to exit
bool (*)(int a, int b)

where 'a' is the status, 'b' is the error value, and returns true if waiting should continue

Definition at line 757 of file sampler.hpp.

759{
760 if(_verbose > 2 || _debug)
761 fprintf(stderr, "[%i]> waiting for pid %i...\n", process::get_id(), wait_pid);
762
763 //----------------------------------------------------------------------------------//
764 //
765 auto print_info = [=](pid_t _pid, int _status, int _errv, int _retv) {
766 if(_debug || _verbose > 2)
767 {
768 fprintf(stderr, "[%i]> return code: %i, error value: %i, status: %i\n", _pid,
769 _retv, _errv, _status);
770 fflush(stderr);
771 }
772 };
773 //
774 //----------------------------------------------------------------------------------//
775 //
776 auto diagnose_status = [=](pid_t _pid, int status) {
777 if(_verbose > 2 || _debug)
778 fprintf(stderr, "[%i]> diagnosing status %i...\n", _pid, status);
779
780 if(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
781 {
782 if(_verbose > 2 || (_debug && _verbose > 0))
783 {
784 fprintf(stderr, "[%i]> program terminated normally with exit code: %i\n",
785 _pid, WEXITSTATUS(status));
786 }
787 // normal terminatation
788 return 0;
789 }
790
791 int ret = WEXITSTATUS(status);
792 if(WIFSTOPPED(status))
793 {
794 int sig = WSTOPSIG(status);
795 // stopped with signal 'sig'
796 if(_debug || _verbose > 3)
797 {
798 fprintf(stderr, "[%i]> program stopped with signal %i. Exit code: %i\n",
799 _pid, sig, ret);
800 }
801 }
802 else if(WCOREDUMP(status))
803 {
804 if(_debug || _verbose > 3)
805 {
806 fprintf(stderr,
807 "[%i]> program terminated and produced a core dump. Exit "
808 "code: %i\n",
809 _pid, ret);
810 }
811 }
812 else if(WIFSIGNALED(status))
813 {
814 ret = WTERMSIG(status);
815 if(_debug || _verbose > 3)
816 {
817 fprintf(stderr,
818 "[%i]> program terminated because it received a signal "
819 "(%i) that was not handled. Exit code: %i\n",
820 _pid, WTERMSIG(status), ret);
821 }
822 }
823 else if(WIFEXITED(status) && WEXITSTATUS(status))
824 {
825 if(ret == 127 && (_debug || _verbose > 3))
826 {
827 fprintf(stderr, "[%i]> execv failed\n", _pid);
828 }
829 else if(_debug || _verbose > 3)
830 {
831 fprintf(stderr,
832 "[%i]> program terminated with a non-zero status. Exit "
833 "code: %i\n",
834 _pid, ret);
835 }
836 }
837 else
838 {
839 if(_debug || _verbose > 3)
840 fprintf(stderr, "[%i]> program terminated abnormally.\n", _pid);
841 ret = EXIT_FAILURE;
842 }
843
844 return ret;
845 };
846 //
847 //----------------------------------------------------------------------------------//
848 //
849 auto waitpid_eintr = [&](pid_t _pid, int& status) {
850 pid_t pid = 0;
851 int errval = 0;
852 int retval = 0;
853
854 while((pid = waitpid(WAIT_ANY, &status, 0)) == -1)
855 {
856 errval = errno;
857 if(errval == EINTR)
858 continue;
859 if(errno != errval)
860 perror("Unexpected error in waitpid_eitr");
861 retval = diagnose_status(pid, status);
862 print_info(pid, status, errval, retval);
863 break;
864 }
865
866 if(errval == ECHILD)
867 {
868 do
869 {
870 retval = kill(_pid, 0);
871 errval = errno;
872 // retval = diagnose_status(_pid, status);
873 // print_info(_pid, status, errval, retval);
874 if(errval == ESRCH || retval == -1)
875 break;
876 std::this_thread::sleep_for(
877 std::chrono::microseconds(get_frequency(units::usec)));
878 } while(true);
879 }
880
881 return errval;
882 };
883 //
884 //----------------------------------------------------------------------------------//
885
886 auto _signals = get_persistent_data().m_signals;
887 int status = 0;
888 int errval = 0;
889
890 // do not wait on self to exit so execute callback until
891 if(_signals.empty() && wait_pid == process::get_id())
892 {
893 do
894 {
895 std::this_thread::sleep_for(
896 std::chrono::microseconds(get_frequency(units::usec)));
897 } while(_callback(wait_pid, status, errval));
898 return diagnose_status(wait_pid, status);
899 }
900
901 // loop while the errno is not EINTR (interrupt) and status designates
902 // it was stopped because of signal
903 int retval = 0;
904 do
905 {
906 status = 0;
907 errval = waitpid_eintr(wait_pid, status);
908 print_info(wait_pid, status, errval, retval);
909 } while((errval == EINTR &&
910 _signals.count(retval = diagnose_status(wait_pid, status)) != 0) &&
911 (_callback(wait_pid, status, errval)));
912
913 print_info(wait_pid, status, errval, retval);
914
915 return diagnose_status(wait_pid, status);
916}
static int64_t get_frequency(int64_t units=units::usec)
Get the frequency of the sampler.
Definition: sampler.hpp:973

Member Data Documentation

◆ m_backtrace

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
bool tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_backtrace = false
protected

Definition at line 349 of file sampler.hpp.

◆ m_bad

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
signal_set_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_bad = {}
protected

Definition at line 353 of file sampler.hpp.

◆ m_data

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
array_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_data = {}
protected

Definition at line 354 of file sampler.hpp.

◆ m_good

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
signal_set_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_good = {}
protected

Definition at line 352 of file sampler.hpp.

◆ m_idx

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
size_t tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_idx = 0
protected

Definition at line 350 of file sampler.hpp.

◆ m_last

template<template< typename... > class CompT, size_t N, typename... Types, int... SigIds>
components_t* tim::sampling::sampler< CompT< Types... >, N, SigIds... >::m_last = nullptr
protected

Definition at line 351 of file sampler.hpp.


The documentation for this struct was generated from the following file: