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