1 //  Copyright (c) 2007-2017 Hartmut Kaiser
2 //  Copyright (c) 2011      Bryce Lelbach
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 /// \file plain_action.hpp
8 
9 #if !defined(HPX_RUNTIME_ACTIONS_PLAIN_ACTION_NOV_14_2008_0706PM)
10 #define HPX_RUNTIME_ACTIONS_PLAIN_ACTION_NOV_14_2008_0706PM
11 
12 #include <hpx/config.hpp>
13 #include <hpx/runtime/actions/basic_action.hpp>
14 #include <hpx/runtime/actions/continuation.hpp>
15 #include <hpx/runtime/naming/address.hpp>
16 #include <hpx/traits/component_type_database.hpp>
17 #include <hpx/util/assert.hpp>
18 #include <hpx/util/detail/pp/cat.hpp>
19 #include <hpx/util/detail/pp/expand.hpp>
20 #include <hpx/util/detail/pp/nargs.hpp>
21 #include <hpx/util/detail/pack.hpp>
22 #include <hpx/util/detail/pp/strip_parens.hpp>
23 #include <hpx/util/unused.hpp>
24 
25 #include <cstdlib>
26 #include <sstream>
27 #include <stdexcept>
28 #include <string>
29 #if defined(__NVCC__) || defined(__CUDACC__)
30 #include <type_traits>
31 #endif
32 #include <utility>
33 
34 #include <hpx/config/warnings_prefix.hpp>
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 namespace hpx { namespace actions
38 {
39     /// \cond NOINTERNAL
40 
41     namespace detail
42     {
43         struct plain_function
44         {
45             // Only localities are valid targets for a plain action
is_target_validhpx::actions::detail::plain_function46             static bool is_target_valid(naming::id_type const& id)
47             {
48                 return naming::is_locality(id);
49             }
50         };
51     }
52 
53     ///////////////////////////////////////////////////////////////////////////
54     //  Specialized generic plain (free) action types allowing to hold a
55     //  different number of arguments
56     ///////////////////////////////////////////////////////////////////////////
57     template <
58         typename R, typename ...Ps,
59         typename TF, TF F, typename Derived>
60     class basic_action_impl<R (*)(Ps...), TF, F, Derived>
61       : public basic_action<detail::plain_function, R(Ps...), Derived>
62     {
63     public:
64 
65         typedef void is_plain_action;
66 
get_action_name(naming::address::address_type)67         static std::string get_action_name(naming::address::address_type /*lva*/)
68         {
69             std::stringstream name;
70             name << "plain action(" << detail::get_action_name<Derived>() << ")";
71             return name.str();
72         }
73 
74         template <typename ...Ts>
invoke(naming::address::address_type,naming::address::component_type comptype,Ts &&...vs)75         static R invoke(naming::address::address_type /*lva*/,
76             naming::address::component_type comptype, Ts&&... vs)
77         {
78             basic_action<detail::plain_function, R(Ps...), Derived>::
79                 increment_invocation_count();
80             return F(std::forward<Ts>(vs)...);
81         }
82     };
83 
84     /// \endcond
85 }}
86 
87 namespace hpx { namespace traits
88 {
89     /// \cond NOINTERNAL
90     template <> HPX_ALWAYS_EXPORT
91     inline components::component_type
get()92     component_type_database<hpx::actions::detail::plain_function>::get()
93     {
94         return hpx::components::component_plain_function;
95     }
96 
97     template <> HPX_ALWAYS_EXPORT
98     inline void
set(components::component_type)99     component_type_database<hpx::actions::detail::plain_function>::set(
100         components::component_type)
101     {
102         HPX_ASSERT(false);      // shouldn't be ever called
103     }
104     /// \endcond
105 }}
106 
107 /// \def HPX_DEFINE_PLAIN_ACTION(func, name)
108 /// \brief Defines a plain action type
109 ///
110 /// \par Example:
111 ///
112 /// \code
113 ///       namespace app
114 ///       {
115 ///           void some_global_function(double d)
116 ///           {
117 ///               cout << d;
118 ///           }
119 ///
120 ///           // This will define the action type 'app::some_global_action' which
121 ///           // represents the function 'app::some_global_function'.
122 ///           HPX_DEFINE_PLAIN_ACTION(some_global_function, some_global_action);
123 ///       }
124 /// \endcode
125 ///
126 /// \note Usually this macro will not be used in user code unless the intent is
127 /// to avoid defining the action_type in global namespace. Normally, the use of
128 /// the macro \a HPX_PLAIN_ACTION is recommended.
129 ///
130 /// \note The macro \a HPX_DEFINE_PLAIN_ACTION can be used with 1 or 2
131 /// arguments. The second argument is optional. The default value for the
132 /// second argument (the typename of the defined action) is derived from the
133 /// name of the function (as passed as the first argument) by appending '_action'.
134 /// The second argument can be omitted only if the first argument with an
135 /// appended suffix '_action' resolves to a valid, unqualified C++ type name.
136 ///
137 #define HPX_DEFINE_PLAIN_ACTION(...)                                          \
138     HPX_DEFINE_PLAIN_ACTION_(__VA_ARGS__)                                     \
139     /**/
140 
141 /// \cond NOINTERNAL
142 
143 #define HPX_DEFINE_PLAIN_DIRECT_ACTION(...)                                   \
144     HPX_DEFINE_PLAIN_DIRECT_ACTION_(__VA_ARGS__)                              \
145     /**/
146 
147 #define HPX_DEFINE_PLAIN_ACTION_(...)                                         \
148     HPX_PP_EXPAND(HPX_PP_CAT(                                                 \
149         HPX_DEFINE_PLAIN_ACTION_, HPX_PP_NARGS(__VA_ARGS__)                   \
150     )(__VA_ARGS__))                                                           \
151     /**/
152 
153 #define HPX_DEFINE_PLAIN_DIRECT_ACTION_(...)                                  \
154     HPX_PP_EXPAND(HPX_PP_CAT(                                                 \
155         HPX_DEFINE_PLAIN_DIRECT_ACTION_, HPX_PP_NARGS(__VA_ARGS__)            \
156     )(__VA_ARGS__))                                                           \
157     /**/
158 
159 #define HPX_DEFINE_PLAIN_ACTION_1(func)                                       \
160     HPX_DEFINE_PLAIN_ACTION_2(func, HPX_PP_CAT(func, _action))                \
161     /**/
162 
163 #if defined(__NVCC__) || defined(__CUDACC__)
164 #define HPX_DEFINE_PLAIN_ACTION_2(func, name)                                 \
165     struct name : hpx::actions::make_action<                                  \
166         typename std::add_pointer<                                            \
167             typename std::remove_pointer<decltype(&func)>::type               \
168         >::type, &func, name>::type {}                                        \
169     /**/
170 #else
171 #define HPX_DEFINE_PLAIN_ACTION_2(func, name)                                 \
172     struct name : hpx::actions::make_action<                                  \
173         decltype(&func), &func, name>::type {}                                \
174     /**/
175 #endif
176 
177 #define HPX_DEFINE_PLAIN_DIRECT_ACTION_1(func)                                \
178     HPX_DEFINE_PLAIN_DIRECT_ACTION_2(func, HPX_PP_CAT(func, _action))         \
179     /**/
180 
181 #define HPX_DEFINE_PLAIN_DIRECT_ACTION_2(func, name)                          \
182     struct name : hpx::actions::make_direct_action<                           \
183         decltype(&func), &func, name>::type {}                                \
184     /**/
185 
186 /// \endcond
187 
188 ///////////////////////////////////////////////////////////////////////////////
189 /// \def HPX_DECLARE_PLAIN_ACTION(func, name)
190 /// \brief Declares a plain action type
191 ///
192 #define HPX_DECLARE_PLAIN_ACTION(...)                                         \
193     HPX_DECLARE_ACTION(__VA_ARGS__)                                           \
194     /**/
195 
196 /// \def HPX_PLAIN_ACTION(func, name)
197 ///
198 /// \brief Defines a plain action type based on the given function
199 /// \a func and registers it with HPX.
200 ///
201 /// The macro \a HPX_PLAIN_ACTION can be used to define a plain action (e.g. an
202 /// action encapsulating a global or free function) based on the given function
203 /// \a func. It defines the action type \a name representing the given function.
204 /// This macro additionally registers the newly define action type with HPX.
205 ///
206 /// The parameter \p func is a global or free (non-member) function which
207 /// should be encapsulated into a plain action. The parameter \p name is the
208 /// name of the action type defined by this macro.
209 ///
210 /// \par Example:
211 ///
212 /// \code
213 ///     namespace app
214 ///     {
215 ///         void some_global_function(double d)
216 ///         {
217 ///             cout << d;
218 ///         }
219 ///     }
220 ///
221 ///     // This will define the action type 'some_global_action' which represents
222 ///     // the function 'app::some_global_function'.
223 ///     HPX_PLAIN_ACTION(app::some_global_function, some_global_action);
224 /// \endcode
225 ///
226 /// \note The macro \a HPX_PLAIN_ACTION has to be used at global namespace even
227 /// if the wrapped function is located in some other namespace. The newly
228 /// defined action type is placed into the global namespace as well.
229 ///
230 /// \note The macro \a HPX_PLAIN_ACTION_ID can be used with 1, 2, or 3 arguments.
231 /// The second and third arguments are optional. The default value for the
232 /// second argument (the typename of the defined action) is derived from the
233 /// name of the function (as passed as the first argument) by appending '_action'.
234 /// The second argument can be omitted only if the first argument with an
235 /// appended suffix '_action' resolves to a valid, unqualified C++ type name.
236 /// The default value for the third argument is \a hpx::components::factory_check.
237 ///
238 /// \note Only one of the forms of this macro \a HPX_PLAIN_ACTION or
239 ///       \a HPX_PLAIN_ACTION_ID should be used for a particular action,
240 ///       never both.
241 ///
242 #define HPX_PLAIN_ACTION(...)                                                 \
243     HPX_PLAIN_ACTION_(__VA_ARGS__)                                            \
244 /**/
245 
246 /// \def HPX_PLAIN_ACTION_ID(func, actionname, actionid)
247 ///
248 /// \brief Defines a plain action type based on the given function \a func and
249 ///   registers it with HPX.
250 ///
251 /// The macro \a HPX_PLAIN_ACTION_ID can be used to define a plain action (e.g. an
252 /// action encapsulating a global or free function) based on the given function
253 /// \a func. It defines the action type \a actionname representing the given function.
254 /// The parameter \a actionid
255 ///
256 /// The parameter \a actionid specifies an unique integer value which will be
257 /// used to represent the action during serialization.
258 ///
259 /// The parameter \p func is a global or free (non-member) function which
260 /// should be encapsulated into a plain action. The parameter \p name is the
261 /// name of the action type defined by this macro.
262 ///
263 /// The second parameter has to be usable as a plain (non-qualified) C++
264 /// identifier, it should not contain special characters which cannot be part
265 /// of a C++ identifier, such as '<', '>', or ':'.
266 ///
267 /// \par Example:
268 ///
269 /// \code
270 ///     namespace app
271 ///     {
272 ///         void some_global_function(double d)
273 ///         {
274 ///             cout << d;
275 ///         }
276 ///     }
277 ///
278 ///     // This will define the action type 'some_global_action' which represents
279 ///     // the function 'app::some_global_function'.
280 ///     HPX_PLAIN_ACTION_ID(app::some_global_function, some_global_action,
281 ///       some_unique_id);
282 /// \endcode
283 ///
284 /// \note The macro \a HPX_PLAIN_ACTION_ID has to be used at global namespace even
285 /// if the wrapped function is located in some other namespace. The newly
286 /// defined action type is placed into the global namespace as well.
287 ///
288 /// \note Only one of the forms of this macro \a HPX_PLAIN_ACTION or
289 ///       \a HPX_PLAIN_ACTION_ID should be used for a particular action,
290 ///       never both.
291 ///
292 #define HPX_PLAIN_ACTION_ID(func, name, id)                                   \
293     HPX_DEFINE_PLAIN_ACTION(func, name);                                      \
294     HPX_REGISTER_ACTION_DECLARATION(name, name);                              \
295     HPX_REGISTER_ACTION_ID(name, name, id);                                   \
296 /**/
297 
298 /// \cond NOINTERNAL
299 
300 #define HPX_PLAIN_DIRECT_ACTION(...)                                          \
301     HPX_PLAIN_DIRECT_ACTION_(__VA_ARGS__)                                     \
302 /**/
303 
304 /// \endcond
305 
306 /// \cond NOINTERNAL
307 
308 // macros for plain actions
309 #define HPX_PLAIN_ACTION_(...)                                                \
310     HPX_PP_EXPAND(HPX_PP_CAT(                                                 \
311         HPX_PLAIN_ACTION_, HPX_PP_NARGS(__VA_ARGS__)                          \
312     )(__VA_ARGS__))                                                           \
313 /**/
314 #define HPX_PLAIN_ACTION_2(func, name)                                        \
315     HPX_DEFINE_PLAIN_ACTION(func, name);                                      \
316     HPX_REGISTER_ACTION_DECLARATION(name, name);                              \
317     HPX_REGISTER_ACTION(name, name);                                          \
318 /**/
319 #define HPX_PLAIN_ACTION_1(func)                                              \
320     HPX_PLAIN_ACTION_2(func, HPX_PP_CAT(func, _action));                      \
321 /**/
322 
323 // same for direct actions
324 #define HPX_PLAIN_DIRECT_ACTION_(...)                                         \
325     HPX_PP_EXPAND(HPX_PP_CAT(                                                 \
326         HPX_PLAIN_DIRECT_ACTION_, HPX_PP_NARGS(__VA_ARGS__)                   \
327     )(__VA_ARGS__))                                                           \
328 /**/
329 #define HPX_PLAIN_DIRECT_ACTION_2(func, name)                                 \
330     HPX_DEFINE_PLAIN_DIRECT_ACTION(func, name);                               \
331     HPX_REGISTER_ACTION_DECLARATION(name, name);                              \
332     HPX_REGISTER_ACTION(name, name);                                          \
333 /**/
334 #define HPX_PLAIN_DIRECT_ACTION_1(func)                                       \
335     HPX_PLAIN_DIRECT_ACTION_2(func, HPX_PP_CAT(func, _action));               \
336 /**/
337 #define HPX_PLAIN_DIRECT_ACTION_ID(func, name, id)                            \
338     HPX_DEFINE_PLAIN_DIRECT_ACTION(func, name);                               \
339     HPX_REGISTER_ACTION_DECLARATION(name, name);                              \
340     HPX_REGISTER_ACTION_ID(name, name, id);                                   \
341 /**/
342 
343 /// \endcond
344 
345 #include <hpx/config/warnings_suffix.hpp>
346 
347 #endif
348 
349