1 // Copyright (C) 2016 John Biddiscombe
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 
6 #ifndef HPT_PARCELSET_POLICIES_VERBS_PERFORMANCE_COUNTER_HPP
7 #define HPT_PARCELSET_POLICIES_VERBS_PERFORMANCE_COUNTER_HPP
8 
9 #include <hpx/config/parcelport_defines.hpp>
10 #include <plugins/parcelport/parcelport_logging.hpp>
11 //
12 #include <atomic>
13 #include <type_traits>
14 #include <iostream>
15 
16 #ifdef HPX_PARCELPORT_LIBFABRIC_HAVE_PERFORMANCE_COUNTERS
17 #  define PERFORMANCE_COUNTER_ENABLED true
18 #else
19 #  define PERFORMANCE_COUNTER_ENABLED false
20 #endif
21 
22 //
23 // This class is intended to provide a simple atomic counter that can be used as a
24 // performance counter, but that can be disabled at compile time so that it
25 // has no performance cost when not used. It is only to avoid a lot of #ifdef
26 // statements in user code that we collect everything in here and then provide
27 // the performance counter that will simply do nothing when disabled - but
28 // still allow code that uses the counters in arithmetic to compile.
29 //
30 namespace hpx {
31 namespace parcelset
32 {
33     template <bool B, typename T = void>
34     using enable_if_t = typename std::enable_if<B, T>::type;
35 
36     template <typename T,
37         bool enabled=PERFORMANCE_COUNTER_ENABLED,
38         typename Enable = enable_if_t<std::is_integral<T>::value>
39     >
40     struct performance_counter {};
41 
42     // --------------------------------------------------------------------
43     // specialization for performance counters Enabled
44     // we provide an atomic<T> that can be incremented or added/subtracted to
45     template <typename T>
46     struct performance_counter<T, true>
47     {
performance_counterhpx::parcelset::performance_counter48         performance_counter() : value_{T()} {}
49 
performance_counterhpx::parcelset::performance_counter50         performance_counter(const T& init) : value_{init} {}
51 
operator Thpx::parcelset::performance_counter52         inline operator T() const { return value_; }
53 
operator =hpx::parcelset::performance_counter54         inline T operator=(const T& x) { return value_ = x; }
55 
operator ++hpx::parcelset::performance_counter56         inline T operator++() { return ++value_; }
57 
operator ++hpx::parcelset::performance_counter58         inline T operator++(int x) { return (value_ += x); }
59 
operator +=hpx::parcelset::performance_counter60         inline T operator+=(const T& rhs) { return (value_ += rhs); }
61 
operator --hpx::parcelset::performance_counter62         inline T operator--() { return --value_; }
63 
operator --hpx::parcelset::performance_counter64         inline T operator--(int x) { return (value_ -= x); }
65 
operator -=hpx::parcelset::performance_counter66         inline T operator-=(const T& rhs) { return (value_ -= rhs); }
67 
operator <<(std::ostream & os,const performance_counter<T,true> & x)68         friend std::ostream& operator<<(std::ostream& os,
69             const performance_counter<T, true>& x)
70         {
71             os << x.value_;
72             return os;
73         }
74 
75         std::atomic<T> value_;
76     };
77 
78     // --------------------------------------------------------------------
79     // specialization for performance counters Disabled
80     // just return dummy values so that arithmetic operations compile ok
81     template <typename T>
82     struct performance_counter<T, false>
83     {
performance_counterhpx::parcelset::performance_counter84         performance_counter() {}
85 
performance_counterhpx::parcelset::performance_counter86         performance_counter(const T&) {}
87 
operator Thpx::parcelset::performance_counter88         inline operator T() const { return 0; }
89 
operator =hpx::parcelset::performance_counter90         inline T operator=(const T&) { return 0; }
91 
operator ++hpx::parcelset::performance_counter92         inline T operator++() { return 0; }
93 
operator ++hpx::parcelset::performance_counter94         inline T operator++(int) { return 0; }
95 
operator +=hpx::parcelset::performance_counter96         inline T operator+=(const T&) { return 0; }
97 
operator --hpx::parcelset::performance_counter98         inline T operator--() { return 0; }
99 
operator --hpx::parcelset::performance_counter100         inline T operator--(int) { return 0; }
101 
operator -=hpx::parcelset::performance_counter102         inline T operator-=(const T&) { return 0; }
103 
operator <<(std::ostream & os,const performance_counter<T,false> & x)104         friend std::ostream& operator<<(std::ostream& os,
105             const performance_counter<T, false>& x)
106         {
107             os << "undefined";
108             return os;
109         }
110     };
111 }}
112 
113 #endif
114 
115