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