1 // Copyright (c) 2017 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #if !defined(HPX_ANNOTATED_FUNCTION_JAN_31_2017_1148AM) 7 #define HPX_ANNOTATED_FUNCTION_JAN_31_2017_1148AM 8 9 #include <hpx/config.hpp> 10 11 #if defined(HPX_HAVE_THREAD_DESCRIPTION) 12 #include <hpx/runtime/threads/thread_data_fwd.hpp> 13 #include <hpx/runtime/threads/thread_helpers.hpp> 14 #include <hpx/traits/get_function_address.hpp> 15 #include <hpx/traits/get_function_annotation.hpp> 16 #include <hpx/util/decay.hpp> 17 #include <hpx/util/invoke.hpp> 18 #include <hpx/util/thread_description.hpp> 19 20 #if HPX_HAVE_ITTNOTIFY != 0 21 #include <hpx/runtime/get_thread_name.hpp> 22 #include <hpx/util/itt_notify.hpp> 23 #elif defined(HPX_HAVE_APEX) 24 #include <hpx/util/apex.hpp> 25 #endif 26 #endif 27 28 #include <cstddef> 29 #include <cstdint> 30 #include <type_traits> 31 #include <utility> 32 33 namespace hpx { namespace util 34 { 35 #if defined(HPX_HAVE_THREAD_DESCRIPTION) 36 /////////////////////////////////////////////////////////////////////////// 37 #if defined(HPX_COMPUTE_DEVICE_CODE) 38 struct annotate_function 39 { 40 HPX_NON_COPYABLE(annotate_function); 41 annotate_functionhpx::util::annotate_function42 explicit annotate_function(char const* name) {} 43 template <typename F> annotate_functionhpx::util::annotate_function44 explicit HPX_HOST_DEVICE annotate_function(F && f) {} 45 46 // add empty (but non-trivial) destructor to silence warnings ~annotate_functionhpx::util::annotate_function47 HPX_HOST_DEVICE ~annotate_function() {} 48 }; 49 #elif HPX_HAVE_ITTNOTIFY != 0 50 struct annotate_function 51 { 52 HPX_NON_COPYABLE(annotate_function); 53 54 explicit annotate_function(char const* name) 55 : task_(thread_domain_, 56 hpx::util::itt::string_handle(name)) 57 {} 58 template <typename F> 59 explicit annotate_function(F && f) 60 : task_(thread_domain_, 61 hpx::traits::get_function_annotation_itt< 62 typename std::decay<F>::type 63 >::call(f)) 64 {} 65 66 private: 67 hpx::util::itt::thread_domain thread_domain_; 68 hpx::util::itt::task task_; 69 }; 70 #else 71 struct annotate_function 72 { 73 HPX_NON_COPYABLE(annotate_function); 74 75 explicit annotate_function(char const* name) 76 : desc_(hpx::threads::get_self_ptr() ? 77 hpx::threads::set_thread_description( 78 hpx::threads::get_self_id(), name) : 79 nullptr) 80 { 81 #if defined(HPX_HAVE_APEX) 82 threads::set_self_apex_data( 83 apex_update_task(threads::get_self_apex_data(), 84 desc_)); 85 #endif 86 } 87 88 template <typename F> 89 explicit annotate_function(F && f) 90 : desc_(hpx::threads::get_self_ptr() ? 91 hpx::threads::set_thread_description( 92 hpx::threads::get_self_id(), 93 hpx::util::thread_description(f)) : 94 nullptr) 95 { 96 #if defined(HPX_HAVE_APEX) 97 threads::set_self_apex_data( 98 apex_update_task(threads::get_self_apex_data(), 99 desc_)); 100 #endif 101 } 102 103 ~annotate_function() 104 { 105 if (hpx::threads::get_self_ptr()) 106 { 107 hpx::threads::set_thread_description( 108 hpx::threads::get_self_id(), desc_); 109 } 110 } 111 112 hpx::util::thread_description desc_; 113 }; 114 #endif 115 116 /////////////////////////////////////////////////////////////////////////// 117 namespace detail 118 { 119 template <typename F> 120 struct annotated_function 121 { annotated_functionhpx::util::detail::annotated_function122 annotated_function() noexcept 123 : name_(nullptr) 124 {} 125 annotated_functionhpx::util::detail::annotated_function126 annotated_function(F const& f, char const* name) 127 : f_(f), name_(name) 128 {} 129 annotated_functionhpx::util::detail::annotated_function130 annotated_function(F && f, char const* name) 131 : f_(std::move(f)), name_(name) 132 {} 133 134 public: 135 template <typename ... Ts> 136 typename invoke_result< 137 typename util::decay_unwrap<F>::type, Ts...>::type operator ()hpx::util::detail::annotated_function138 operator()(Ts && ... ts) 139 { 140 annotate_function func(name_); 141 return util::invoke(f_, std::forward<Ts>(ts)...); 142 } 143 144 template <typename Archive> serializehpx::util::detail::annotated_function145 void serialize(Archive& ar, unsigned int const /*version*/) 146 { 147 ar & f_; 148 } 149 get_function_addresshpx::util::detail::annotated_function150 std::size_t get_function_address() const 151 { 152 return traits::get_function_address< 153 typename util::decay_unwrap<F>::type 154 >::call(f_); 155 } 156 get_function_annotationhpx::util::detail::annotated_function157 char const* get_function_annotation() const noexcept 158 { 159 return name_ ? name_ : typeid(f_).name(); 160 } 161 162 private: 163 typename util::decay_unwrap<F>::type f_; 164 char const* name_; 165 }; 166 } 167 168 template <typename F> 169 detail::annotated_function<typename std::decay<F>::type> annotated_function(F && f,char const * name=nullptr)170 annotated_function(F && f, char const* name = nullptr) 171 { 172 typedef detail::annotated_function< 173 typename std::decay<F>::type 174 > result_type; 175 176 return result_type(std::forward<F>(f), name); 177 } 178 179 #else 180 /////////////////////////////////////////////////////////////////////////// 181 struct annotate_function 182 { 183 HPX_NON_COPYABLE(annotate_function); 184 185 explicit annotate_function(char const* /*name*/) {} 186 template <typename F> 187 explicit HPX_HOST_DEVICE annotate_function(F && /*f*/) {} 188 189 // add empty (but non-trivial) destructor to silence warnings 190 HPX_HOST_DEVICE ~annotate_function() {} 191 }; 192 193 /////////////////////////////////////////////////////////////////////////// 194 template <typename F> 195 F && annotated_function(F && f, char const* = nullptr) 196 { 197 return std::forward<F>(f); 198 } 199 #endif 200 }} 201 202 #if defined(HPX_HAVE_THREAD_DESCRIPTION) 203 namespace hpx { namespace traits 204 { 205 template <typename F> 206 struct get_function_address<util::detail::annotated_function<F> > 207 { 208 static std::size_t callhpx::traits::get_function_address209 call(util::detail::annotated_function<F> const& f) noexcept 210 { 211 return f.get_function_address(); 212 } 213 }; 214 215 template <typename F> 216 struct get_function_annotation<util::detail::annotated_function<F> > 217 { 218 static char const* callhpx::traits::get_function_annotation219 call(util::detail::annotated_function<F> const& f) noexcept 220 { 221 return f.get_function_annotation(); 222 } 223 }; 224 }} 225 #endif 226 227 #endif 228