| Line | % of fetches | Source |
|---|---|---|
| 1 | // Copyright (c) 2007-2015 Hartmut Kaiser | |
| 2 | // Copyright (c) 2011 Bryce Lelbach | |
| 3 | // Copyright (c) 2011 Thomas Heller | |
| 4 | // | |
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
| 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
| 7 | ||
| 8 | #if !defined(HPX_RUNTIME_SUPPORT_JUN_02_2008_1145AM) | |
| 9 | #define HPX_RUNTIME_SUPPORT_JUN_02_2008_1145AM | |
| 10 | ||
| 11 | #include <hpx/config.hpp> | |
| 12 | #include <hpx/throw_exception.hpp> | |
| 13 | #if defined(HPX_HAVE_SECURITY) | |
| 14 | #include <hpx/traits/action_capability_provider.hpp> | |
| 15 | #endif | |
| 16 | #include <hpx/lcos/local/condition_variable.hpp> | |
| 17 | #include <hpx/lcos/local/mutex.hpp> | |
| 18 | #include <hpx/lcos/local/spinlock.hpp> | |
| 19 | #include <hpx/performance_counters/counters.hpp> | |
| 20 | #include <hpx/plugins/plugin_factory_base.hpp> | |
| 21 | #include <hpx/runtime/actions/component_action.hpp> | |
| 22 | #include <hpx/runtime/actions/manage_object_action.hpp> | |
| 23 | #include <hpx/runtime/agas/gva.hpp> | |
| 24 | #include <hpx/runtime/components/component_factory_base.hpp> | |
| 25 | #include <hpx/runtime/components/component_type.hpp> | |
| 26 | #include <hpx/runtime/components/server/create_component.hpp> | |
| 27 | #include <hpx/runtime/components/static_factory_data.hpp> | |
| 28 | #include <hpx/runtime/get_lva.hpp> | |
| 29 | #include <hpx/runtime/find_here.hpp> | |
| 30 | #include <hpx/runtime/parcelset/locality.hpp> | |
| 31 | #include <hpx/traits/action_does_termination_detection.hpp> | |
| 32 | #include <hpx/traits/is_component.hpp> | |
| 33 | #include <hpx/util/bind.hpp> | |
| 34 | #include <hpx/util/functional/new.hpp> | |
| 35 | #include <hpx/util/one_size_heap_list_base.hpp> | |
| 36 | #include <hpx/util/plugin.hpp> | |
| 37 | #include <hpx/util/unlock_guard.hpp> | |
| 38 | #include <hpx/util_fwd.hpp> | |
| 39 | ||
| 40 | #include <boost/atomic.hpp> | |
| 41 | #include <boost/program_options/options_description.hpp> | |
| 42 | #include <boost/thread/condition.hpp> | |
| 43 | #include <boost/thread/mutex.hpp> | |
| 44 | ||
| 45 | #include <cstddef> | |
| 46 | #include <cstdint> | |
| 47 | #include <list> | |
| 48 | #include <map> | |
| 49 | #include <memory> | |
| 50 | #include <mutex> | |
| 51 | #include <set> | |
| 52 | #include <sstream> | |
| 53 | #include <string> | |
| 54 | #include <type_traits> | |
| 55 | #include <utility> | |
| 56 | #include <vector> | |
| 57 | ||
| 58 | #include <hpx/config/warnings_prefix.hpp> | |
| 59 | ||
| 60 | // Fast termination detection does not work, currently, as the return actions | |
| 61 | // generated by the futures used by hpx::reduce and hpx::broadcast mark the | |
| 62 | // sender as black. This causes an infinite loop while waiting for the Dijkstra | |
| 63 | // termination detection to return. | |
| 64 | ||
| 65 | namespace hpx { namespace components { namespace server | |
| 66 | { | |
| 67 | /////////////////////////////////////////////////////////////////////////// | |
| 68 | class runtime_support | |
| 69 | { | |
| 70 | private: | |
| 71 | typedef lcos::local::spinlock component_map_mutex_type; | |
| 72 | typedef lcos::local::spinlock plugin_map_mutex_type; | |
| 73 | typedef boost::mutex mutex_type; | |
| 74 | ||
| 75 | struct component_factory | |
| 76 | { | |
| 77 | component_factory() : second(), isenabled(false) {} | |
| 78 | ||
| 79 | component_factory( | |
| 80 | std::shared_ptr<component_factory_base> const& f, | |
| 81 | hpx::util::plugin::dll const& d, bool enabled = true) | |
| 82 | : first(f), second(d), isenabled(enabled) | |
| 83 | {}; | |
| 84 | ||
| 85 | component_factory( | |
| 86 | std::shared_ptr<component_factory_base> const& f, | |
| 87 | bool enabled = true) | |
| 88 | : first(f), second(), isenabled(enabled) | |
| 89 | {}; | |
| 90 | ||
| 91 | std::shared_ptr<component_factory_base> first; | |
| 92 | hpx::util::plugin::dll second; | |
| 93 | bool isenabled; | |
| 94 | }; | |
| 95 | typedef component_factory component_factory_type; | |
| 96 | typedef std::map<component_type, component_factory_type> component_map_type; | |
| 97 | ||
| 98 | struct plugin_factory | |
| 99 | { | |
| 100 | plugin_factory( | |
| 101 | std::shared_ptr<plugins::plugin_factory_base> const& f, | |
| 102 | hpx::util::plugin::dll const& d, bool enabled) | |
| 103 | : first(f), second(d), isenabled(enabled) | |
| 104 | {} | |
| 105 | ||
| 106 | std::shared_ptr<plugins::plugin_factory_base> first; | |
| 107 | hpx::util::plugin::dll const& second; | |
| 108 | bool isenabled; | |
| 109 | }; | |
| 110 | typedef plugin_factory plugin_factory_type; | |
| 111 | typedef std::map<std::string, plugin_factory_type> plugin_map_type; | |
| 112 | ||
| 113 | typedef std::map<std::string, hpx::util::plugin::dll> modules_map_type; | |
| 114 | typedef std::vector<static_factory_load_data_type> static_modules_type; | |
| 115 | ||
| 116 | public: | |
| 117 | typedef runtime_support type_holder; | |
| 118 | ||
| 119 | static component_type get_component_type() | |
| 120 | { | |
| 121 | return components::get_component_type<runtime_support>(); | |
| 122 | } | |
| 123 | static void set_component_type(component_type t) | |
| 124 | { | |
| 125 | components::set_component_type<runtime_support>(t); | |
| 126 | } | |
| 127 | ||
| 128 | // constructor | |
| 129 | runtime_support(hpx::util::runtime_configuration & cfg); | |
| 130 | ||
| 131 | ~runtime_support() | |
| 132 | { | |
| 133 | tidy(); | |
| 134 | } | |
| 135 | ||
| 136 | /// \brief finalize() will be called just before the instance gets | |
| 137 | /// destructed | |
| 138 | /// | |
| 139 | /// \param self [in] The HPX \a thread used to execute this function. | |
| 140 | /// \param appl [in] The applier to be used for finalization of the | |
| 141 | /// component instance. | |
| 142 | void finalize() {} | |
| 143 | ||
| 144 | void delete_function_lists(); | |
| 145 | void tidy(); | |
| 146 | ||
| 147 | // This component type requires valid locality id for its actions to | |
| 148 | // be invoked | |
| 149 | static bool is_target_valid(naming::id_type const& id) | |
| 150 | { | |
| 151 | return naming::is_locality(id); | |
| 152 | } | |
| 153 | ||
| 154 | /////////////////////////////////////////////////////////////////////// | |
| 155 | // exposed functionality of this component | |
| 156 | ||
| 157 | /// \brief Action to create N new default constructed components | |
| 158 | std::vector<naming::gid_type> bulk_create_components( | |
| 159 | components::component_type type, std::size_t count); | |
| 160 | ||
| 161 | /// \brief Actions to create new objects | |
| 162 | template <typename Component> | |
| 163 | naming::gid_type create_component(); | |
| 164 | ||
| 165 | template <typename Component, typename T, typename ...Ts> | |
| 166 | naming::gid_type create_component(T v, Ts... vs); | |
| 167 | ||
| 168 | template <typename Component> | |
| 169 | std::vector<naming::gid_type> bulk_create_component(std::size_t count); | |
| 170 | ||
| 171 | template <typename Component, typename T, typename ...Ts> | |
| 172 | std::vector<naming::gid_type> bulk_create_component( | |
| 173 | std::size_t count, T v, Ts... vs); | |
| 174 | ||
| 175 | template <typename Component> | |
| 176 | naming::gid_type copy_create_component( | |
| 177 | std::shared_ptr<Component> const& p, bool); | |
| 178 | ||
| 179 | template <typename Component> | |
| 180 | naming::gid_type migrate_component_to_here( | |
| 181 | std::shared_ptr<Component> const& p, naming::id_type); | |
| 182 | ||
| 183 | /// \brief Action to create new memory block | |
| 184 | naming::gid_type create_memory_block(std::size_t count, | |
| 185 | hpx::actions::manage_object_action_base const& act); | |
| 186 | ||
| 187 | /// \brief Action to delete existing components | |
| 188 | /// | |
| 189 | /// \param count [in] This GID is a count of the number of components | |
| 190 | /// to destroy. It does not represent a global address. | |
| 191 | void free_component(agas::gva const&, naming::gid_type const& gid, | |
| 192 | std::uint64_t count); | |
| 193 | ||
| 194 | /// \brief Gracefully shutdown this runtime system instance | |
| 195 | void shutdown(double timeout, naming::id_type const& respond_to); | |
| 196 | ||
| 197 | /// \brief Gracefully shutdown runtime system instances on all localities | |
| 198 | void shutdown_all(double timeout); | |
| 199 | ||
| 200 | /// \brief Shutdown this runtime system instance | |
| 201 | HPX_ATTRIBUTE_NORETURN void terminate( | |
| 202 | naming::id_type const& respond_to); | |
| 203 | ||
| 204 | void terminate_act(naming::id_type const& id) { terminate(id); } | |
| 205 | ||
| 206 | /// \brief Shutdown runtime system instances on all localities | |
| 207 | HPX_ATTRIBUTE_NORETURN void terminate_all(); | |
| 208 | ||
| 209 | void terminate_all_act() { terminate_all(); } | |
| 210 | ||
| 211 | /// \brief Retrieve configuration information | |
| 212 | util::section get_config(); | |
| 213 | ||
| 214 | /// \brief Update the given name mapping into the AGAS cache of this | |
| 215 | /// locality. | |
| 216 | void update_agas_cache_entry(naming::gid_type const&, | |
| 217 | naming::address const&, std::uint64_t, std::uint64_t); | |
| 218 | ||
| 219 | /// \brief Load all components on this locality. | |
| 220 | int load_components(); | |
| 221 | ||
| 222 | void call_startup_functions(bool pre_startup); | |
| 223 | void call_shutdown_functions(bool pre_shutdown); | |
| 224 | ||
| 225 | /// \brief Force a garbage collection operation in the AGAS layer. | |
| 226 | void garbage_collect(); | |
| 227 | ||
| 228 | /// \brief Create the given performance counter instance. | |
| 229 | naming::gid_type create_performance_counter( | |
| 230 | performance_counters::counter_info const& info); | |
| 231 | ||
| 232 | /// \brief Return the current instance count for the given component | |
| 233 | /// type | |
| 234 | std::int32_t get_instance_count(components::component_type); | |
| 235 | ||
| 236 | /// \brief Remove the given locality from our connection cache | |
| 237 | void remove_from_connection_cache(naming::gid_type const& gid, | |
| 238 | parcelset::endpoints_type const& eps); | |
| 239 | ||
| 240 | /// \brief termination detection | |
| 241 | #if defined(HPX_USE_FAST_DIJKSTRA_TERMINATION_DETECTION) | |
| 242 | bool dijkstra_termination(); | |
| 243 | #else | |
| 244 | void dijkstra_termination(std::uint32_t initiating_locality_id, | |
| 245 | std::uint32_t num_localities, bool dijkstra_token); | |
| 246 | #endif | |
| 247 | ||
| 248 | /////////////////////////////////////////////////////////////////////// | |
| 249 | // Each of the exposed functions needs to be encapsulated into a action | |
| 250 | // type, allowing to generate all require boilerplate code for threads, | |
| 251 | // serialization, etc. | |
| 252 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, bulk_create_components); | |
| 253 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, create_memory_block); | |
| 254 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, load_components); | |
| 255 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, call_startup_functions); | |
| 256 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, call_shutdown_functions); | |
| 257 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, free_component, | |
| 258 | free_component_action); | |
| 259 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, shutdown); | |
| 260 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, shutdown_all); | |
| 261 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, terminate_act, | |
| 262 | terminate_action); | |
| 263 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, terminate_all_act, | |
| 264 | terminate_all_action); | |
| 265 | ||
| 266 | // even if this is not a short/minimal action, we still execute it | |
| 267 | // directly to avoid a deadlock condition inside the thread manager | |
| 268 | // waiting for this thread to finish, which waits for the thread | |
| 269 | // manager to exit | |
| 270 | HPX_DEFINE_COMPONENT_DIRECT_ACTION(runtime_support, get_config); | |
| 271 | ||
| 272 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, update_agas_cache_entry); | |
| 273 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, garbage_collect); | |
| 274 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, create_performance_counter); | |
| 275 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, get_instance_count); | |
| 276 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, remove_from_connection_cache); | |
| 277 | ||
| 278 | HPX_DEFINE_COMPONENT_ACTION(runtime_support, dijkstra_termination); | |
| 279 | ||
| 280 | /////////////////////////////////////////////////////////////////////// | |
| 281 | /// \brief Start the runtime_support component | |
| 282 | void run(); | |
| 283 | ||
| 284 | /// \brief Wait for the runtime_support component to notify the calling | |
| 285 | /// thread. | |
| 286 | /// | |
| 287 | /// This function will be called from the main thread, causing it to | |
| 288 | /// block while the HPX functionality is executed. The main thread will | |
| 289 | /// block until the shutdown_action is executed, which in turn notifies | |
| 290 | /// all waiting threads. | |
| 291 | void wait(); | |
| 292 | ||
| 293 | /// \brief Notify all waiting (blocking) threads allowing the system to | |
| 294 | /// be properly stopped. | |
| 295 | /// | |
| 296 | /// \note This function can be called from any thread. | |
| 297 | void stop(double timeout, naming::id_type const& respond_to, | |
| 298 | bool remove_from_remote_caches); | |
| 299 | ||
| 300 | /// called locally only | |
| 301 | void stopped(); | |
| 302 | void notify_waiting_main(); | |
| 303 | ||
| 304 | bool was_stopped() const { return stopped_; } | |
| 305 | ||
| 306 | void add_pre_startup_function(startup_function_type f) | |
| 307 | { | |
| 308 | std::lock_guard<lcos::local::spinlock> l(globals_mtx_); | |
| 309 | pre_startup_functions_.push_back(std::move(f)); | |
| 310 | } | |
| 311 | ||
| 312 | void add_startup_function(startup_function_type f) | |
| 313 | { | |
| 314 | std::lock_guard<lcos::local::spinlock> l(globals_mtx_); | |
| 315 | startup_functions_.push_back(std::move(f)); | |
| 316 | } | |
| 317 | ||
| 318 | void add_pre_shutdown_function(shutdown_function_type f) | |
| 319 | { | |
| 320 | std::lock_guard<lcos::local::spinlock> l(globals_mtx_); | |
| 321 | pre_shutdown_functions_.push_back(std::move(f)); | |
| 322 | } | |
| 323 | ||
| 324 | void add_shutdown_function(shutdown_function_type f) | |
| 325 | { | |
| 326 | std::lock_guard<lcos::local::spinlock> l(globals_mtx_); | |
| 327 | shutdown_functions_.push_back(std::move(f)); | |
| 328 | } | |
| 329 | ||
| 330 | bool keep_factory_alive(component_type t); | |
| 331 | ||
| 332 | void remove_here_from_connection_cache(); | |
| 333 | ||
| 334 | /////////////////////////////////////////////////////////////////////// | |
| 335 | void register_message_handler(char const* message_handler_type, | |
| 336 | char const* action, error_code& ec); | |
| 337 | parcelset::policies::message_handler* create_message_handler( | |
| 338 | char const* message_handler_type, char const* action, | |
| 339 | parcelset::parcelport* pp, std::size_t num_messages, | |
| 340 | std::size_t interval, error_code& ec); | |
| 341 | serialization::binary_filter* create_binary_filter( | |
| 342 | char const* binary_filter_type, bool compress, | |
| 343 | serialization::binary_filter* next_filter, error_code& ec); | |
| 344 | ||
| 345 | // notify of message being sent | |
| 346 | void dijkstra_make_black(); | |
| 347 | ||
| 348 | #if defined(HPX_HAVE_SECURITY) | |
| 349 | components::security::capability get_factory_capabilities( | |
| 350 | components::component_type type); | |
| 351 | #endif | |
| 352 | ||
| 353 | protected: | |
| 354 | // Load all components from the ini files found in the configuration | |
| 355 | int load_components(util::section& ini, naming::gid_type const& prefix, | |
| 356 | naming::resolver_client& agas_client, | |
| 357 | boost::program_options::options_description& options, | |
| 358 | std::set<std::string>& startup_handled); | |
| 359 | ||
| 360 | #if !defined(HPX_HAVE_STATIC_LINKING) | |
| 361 | bool load_component(hpx::util::plugin::dll& d, | |
| 362 | util::section& ini, std::string const& instance, | |
| 363 | std::string const& component, boost::filesystem::path const& lib, | |
| 364 | naming::gid_type const& prefix, naming::resolver_client& agas_client, | |
| 365 | bool isdefault, bool isenabled, | |
| 366 | boost::program_options::options_description& options, | |
| 367 | std::set<std::string>& startup_handled); | |
| 368 | bool load_component_dynamic( | |
| 369 | util::section& ini, std::string const& instance, | |
| 370 | std::string const& component, boost::filesystem::path lib, | |
| 371 | naming::gid_type const& prefix, naming::resolver_client& agas_client, | |
| 372 | bool isdefault, bool isenabled, | |
| 373 | boost::program_options::options_description& options, | |
| 374 | std::set<std::string>& startup_handled); | |
| 375 | ||
| 376 | bool load_startup_shutdown_functions(hpx::util::plugin::dll& d, | |
| 377 | error_code& ec); | |
| 378 | bool load_commandline_options(hpx::util::plugin::dll& d, | |
| 379 | boost::program_options::options_description& options, | |
| 380 | error_code& ec); | |
| 381 | #endif | |
| 382 | ||
| 383 | bool load_component_static( | |
| 384 | util::section& ini, std::string const& instance, | |
| 385 | std::string const& component, boost::filesystem::path const& lib, | |
| 386 | naming::gid_type const& prefix, naming::resolver_client& agas_client, | |
| 387 | bool isdefault, bool isenabled, | |
| 388 | boost::program_options::options_description& options, | |
| 389 | std::set<std::string>& startup_handled); | |
| 390 | bool load_startup_shutdown_functions_static(std::string const& module, | |
| 391 | error_code& ec); | |
| 392 | bool load_commandline_options_static( | |
| 393 | std::string const& module, | |
| 394 | boost::program_options::options_description& options, | |
| 395 | error_code& ec); | |
| 396 | ||
| 397 | // Load all plugins from the ini files found in the configuration | |
| 398 | bool load_plugins(util::section& ini, | |
| 399 | boost::program_options::options_description& options, | |
| 400 | std::set<std::string>& startup_handled); | |
| 401 | ||
| 402 | #if !defined(HPX_HAVE_STATIC_LINKING) | |
| 403 | bool load_plugin(hpx::util::plugin::dll& d, | |
| 404 | util::section& ini, std::string const& instance, | |
| 405 | std::string const& component, boost::filesystem::path const& lib, | |
| 406 | bool isenabled, | |
| 407 | boost::program_options::options_description& options, | |
| 408 | std::set<std::string>& startup_handled); | |
| 409 | bool load_plugin_dynamic( | |
| 410 | util::section& ini, std::string const& instance, | |
| 411 | std::string const& component, boost::filesystem::path lib, | |
| 412 | bool isenabled, | |
| 413 | boost::program_options::options_description& options, | |
| 414 | std::set<std::string>& startup_handled); | |
| 415 | #endif | |
| 416 | ||
| 417 | // the name says it all | |
| 418 | std::size_t dijkstra_termination_detection( | |
| 419 | std::vector<naming::id_type> const& locality_ids); | |
| 420 | ||
| 421 | #if !defined(HPX_USE_FAST_DIJKSTRA_TERMINATION_DETECTION) | |
| 422 | void send_dijkstra_termination_token( | |
| 423 | std::uint32_t target_locality_id, | |
| 424 | std::uint32_t initiating_locality_id, | |
| 425 | std::uint32_t num_localities, bool dijkstra_token); | |
| 426 | #endif | |
| 427 | ||
| 428 | private: | |
| 429 | mutex_type mtx_; | |
| 430 | boost::condition_variable wait_condition_; | |
| 431 | boost::condition_variable stop_condition_; | |
| 432 | bool stopped_; | |
| 433 | bool terminated_; | |
| 434 | bool dijkstra_color_; // false: white, true: black | |
| 435 | boost::atomic<bool> shutdown_all_invoked_; | |
| 436 | ||
| 437 | typedef hpx::lcos::local::spinlock dijkstra_mtx_type; | |
| 438 | dijkstra_mtx_type dijkstra_mtx_; | |
| 439 | lcos::local::condition_variable_any dijkstra_cond_; | |
| 440 | ||
| 441 | component_map_mutex_type cm_mtx_; | |
| 442 | plugin_map_mutex_type p_mtx_; | |
| 443 | ||
| 444 | component_map_type components_; | |
| 445 | plugin_map_type plugins_; | |
| 446 | modules_map_type & modules_; | |
| 447 | static_modules_type static_modules_; | |
| 448 | ||
| 449 | lcos::local::spinlock globals_mtx_; | |
| 450 | std::list<startup_function_type> pre_startup_functions_; | |
| 451 | std::list<startup_function_type> startup_functions_; | |
| 452 | std::list<shutdown_function_type> pre_shutdown_functions_; | |
| 453 | std::list<shutdown_function_type> shutdown_functions_; | |
| 454 | }; | |
| 455 | ||
| 456 | /////////////////////////////////////////////////////////////////////////// | |
| 457 | // Functions wrapped by creat_component actions below | |
| 458 | template <typename Component> | |
| 459 | naming::gid_type runtime_support::create_component() | |
| 460 | { | |
| 461 | components::component_type const type = | |
| 462 | components::get_component_type< | |
| 463 | typename Component::wrapped_type>(); | |
| 464 | ||
| 465 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 466 | component_map_type::const_iterator it = components_.find(type); | |
| 467 | if (it == components_.end()) { | |
| 468 | std::ostringstream strm; | |
| 469 | strm << "attempt to create component instance of " | |
| 470 | << "invalid/unknown type: " | |
| 471 | << components::get_component_type_name(type) | |
| 472 | << " (component type not found in map)"; | |
| 473 | ||
| 474 | l.unlock(); | |
| 475 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 476 | "runtime_support::create_component", | |
| 477 | strm.str()); | |
| 478 | return naming::invalid_gid; | |
| 479 | } | |
| 480 | ||
| 481 | if (!(*it).second.first) { | |
| 482 | std::ostringstream strm; | |
| 483 | strm << "attempt to create component instance of " | |
| 484 | << "invalid/unknown type: " | |
| 485 | << components::get_component_type_name(type) | |
| 486 | << " (map entry is nullptr)"; | |
| 487 | ||
| 488 | l.unlock(); | |
| 489 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 490 | "runtime_support::create_component", | |
| 491 | strm.str()); | |
| 492 | return naming::invalid_gid; | |
| 493 | } | |
| 494 | ||
| 495 | naming::gid_type id; | |
| 496 | std::shared_ptr<component_factory_base> factory((*it).second.first); | |
| 497 | { | |
| 498 | util::unlock_guard<std::unique_lock<component_map_mutex_type> > ul(l); | |
| 499 | id = factory->create(); | |
| 500 | } | |
| 501 | LRT_(info) << "successfully created component " << id | |
| 502 | << " of type: " << components::get_component_type_name(type); | |
| 503 | ||
| 504 | return id; | |
| 505 | } | |
| 506 | ||
| 507 | template <typename Component, typename T, typename ...Ts> | |
| 508 | naming::gid_type runtime_support::create_component(T v, Ts... vs) | |
| 509 | { | |
| 510 | components::component_type const type = | |
| 511 | components::get_component_type< | |
| 512 | typename Component::wrapped_type>(); | |
| 513 | ||
| 514 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 515 | component_map_type::const_iterator it = components_.find(type); | |
| 516 | if (it == components_.end()) { | |
| 517 | std::ostringstream strm; | |
| 518 | strm << "attempt to create component instance of " | |
| 519 | << "invalid/unknown type: " | |
| 520 | << components::get_component_type_name(type) | |
| 521 | << " (component type not found in map)"; | |
| 522 | ||
| 523 | l.unlock(); | |
| 524 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 525 | "runtime_support::create_component", | |
| 526 | strm.str()); | |
| 527 | return naming::invalid_gid; | |
| 528 | } | |
| 529 | ||
| 530 | if (!(*it).second.first) { | |
| 531 | std::ostringstream strm; | |
| 532 | strm << "attempt to create component instance of " | |
| 533 | << "invalid/unknown type: " | |
| 534 | << components::get_component_type_name(type) | |
| 535 | << " (map entry is nullptr)"; | |
| 536 | ||
| 537 | l.unlock(); | |
| 538 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 539 | "runtime_support::create_component", | |
| 540 | strm.str()); | |
| 541 | return naming::invalid_gid; | |
| 542 | } | |
| 543 | ||
| 544 | naming::gid_type id; | |
| 545 | std::shared_ptr<component_factory_base> factory((*it).second.first); | |
| 546 | { | |
| 547 | util::unlock_guard<std::unique_lock<component_map_mutex_type> > ul(l); | |
| 548 | ||
| 549 | typedef typename Component::wrapping_type wrapping_type; | |
| 550 | ||
| 551 | // Note, T and Ts can't be (non-const) references, and parameters | |
| 552 | // should be moved to allow for move-only constructor argument | |
| 553 | // types. | |
| 554 | id = factory->create_with_args( | |
| 555 | detail::construct_function<wrapping_type>( | |
| 556 | std::move(v), std::move(vs)...)); | |
| 557 | } | |
| 558 | LRT_(info) << "successfully created component " << id | |
| 559 | << " of type: " << components::get_component_type_name(type); | |
| 560 | ||
| 561 | return id; | |
| 562 | } | |
| 563 | ||
| 564 | template <typename Component> | |
| 565 | std::vector<naming::gid_type> | |
| 566 | runtime_support::bulk_create_component(std::size_t count) | |
| 567 | { | |
| 568 | components::component_type const type = | |
| 569 | components::get_component_type< | |
| 570 | typename Component::wrapped_type>(); | |
| 571 | ||
| 572 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 573 | component_map_type::const_iterator it = components_.find(type); | |
| 574 | if (it == components_.end()) { | |
| 575 | std::ostringstream strm; | |
| 576 | strm << "attempt to create component(s) instance of " | |
| 577 | << "invalid/unknown type: " | |
| 578 | << components::get_component_type_name(type) | |
| 579 | << " (component type not found in map)"; | |
| 580 | ||
| 581 | l.unlock(); | |
| 582 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 583 | "runtime_support::create_component", | |
| 584 | strm.str()); | |
| 585 | return std::vector<naming::gid_type>(); | |
| 586 | } | |
| 587 | ||
| 588 | if (!(*it).second.first) { | |
| 589 | std::ostringstream strm; | |
| 590 | strm << "attempt to create component instance(s) of " | |
| 591 | << "invalid/unknown type: " | |
| 592 | << components::get_component_type_name(type) | |
| 593 | << " (map entry is nullptr)"; | |
| 594 | ||
| 595 | l.unlock(); | |
| 596 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 597 | "runtime_support::create_component", | |
| 598 | strm.str()); | |
| 599 | return std::vector<naming::gid_type>(); | |
| 600 | } | |
| 601 | ||
| 602 | std::vector<naming::gid_type> ids; | |
| 603 | ids.reserve(count); | |
| 604 | ||
| 605 | std::shared_ptr<component_factory_base> factory((*it).second.first); | |
| 606 | { | |
| 607 | util::unlock_guard<std::unique_lock<component_map_mutex_type> > ul(l); | |
| 608 | for (std::size_t i = 0; i != count; ++i) | |
| 609 | { | |
| 610 | ids.push_back(factory->create()); | |
| 611 | } | |
| 612 | } | |
| 613 | LRT_(info) << "successfully created " << count //-V128 | |
| 614 | << " component(s) of type: " | |
| 615 | << components::get_component_type_name(type); | |
| 616 | ||
| 617 | return ids; | |
| 618 | } | |
| 619 | ||
| 620 | template <typename Component, typename T, typename ...Ts> | |
| 621 | std::vector<naming::gid_type> | |
| 622 | runtime_support::bulk_create_component(std::size_t count, T v, Ts ... vs) | |
| 623 | { | |
| 624 | components::component_type const type = | |
| 625 | components::get_component_type< | |
| 626 | typename Component::wrapped_type>(); | |
| 627 | ||
| 628 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 629 | component_map_type::const_iterator it = components_.find(type); | |
| 630 | if (it == components_.end()) { | |
| 631 | std::ostringstream strm; | |
| 632 | strm << "attempt to create component(s) instance of " | |
| 633 | << "invalid/unknown type: " | |
| 634 | << components::get_component_type_name(type) | |
| 635 | << " (component type not found in map)"; | |
| 636 | ||
| 637 | l.unlock(); | |
| 638 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 639 | "runtime_support::create_component", | |
| 640 | strm.str()); | |
| 641 | return std::vector<naming::gid_type>(); | |
| 642 | } | |
| 643 | ||
| 644 | if (!(*it).second.first) { | |
| 645 | std::ostringstream strm; | |
| 646 | strm << "attempt to create component instance(s) of " | |
| 647 | << "invalid/unknown type: " | |
| 648 | << components::get_component_type_name(type) | |
| 649 | << " (map entry is nullptr)"; | |
| 650 | ||
| 651 | l.unlock(); | |
| 652 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 653 | "runtime_support::create_component", | |
| 654 | strm.str()); | |
| 655 | return std::vector<naming::gid_type>(); | |
| 656 | } | |
| 657 | ||
| 658 | std::vector<naming::gid_type> ids; | |
| 659 | ids.reserve(count); | |
| 660 | ||
| 661 | std::shared_ptr<component_factory_base> factory((*it).second.first); | |
| 662 | { | |
| 663 | util::unlock_guard<std::unique_lock<component_map_mutex_type> > ul(l); | |
| 664 | for (std::size_t i = 0; i != count; ++i) | |
| 665 | { | |
| 666 | typedef typename Component::wrapping_type wrapping_type; | |
| 667 | ||
| 668 | // Note, T and Ts can't be (non-const) references, and parameters | |
| 669 | // should be moved to allow for move-only constructor argument | |
| 670 | // types. | |
| 671 | ids.push_back( | |
| 672 | factory->create_with_args( | |
| 673 | detail::construct_function<wrapping_type>(v, vs...) | |
| 674 | ) | |
| 675 | ); | |
| 676 | } | |
| 677 | } | |
| 678 | LRT_(info) << "successfully created " << count //-V128 | |
| 679 | << " component(s) of type: " | |
| 680 | << components::get_component_type_name(type); | |
| 681 | ||
| 682 | return ids; | |
| 683 | } | |
| 684 | ||
| 685 | template <typename Component> | |
| 686 | naming::gid_type runtime_support::copy_create_component( | |
| 687 | std::shared_ptr<Component> const& p, bool local_op) | |
| 688 | { | |
| 689 | components::component_type const type = | |
| 690 | components::get_component_type< | |
| 691 | typename Component::wrapped_type>(); | |
| 692 | ||
| 693 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 694 | component_map_type::const_iterator it = components_.find(type); | |
| 695 | if (it == components_.end()) { | |
| 696 | std::ostringstream strm; | |
| 697 | strm << "attempt to create component instance of " | |
| 698 | << "invalid/unknown type: " | |
| 699 | << components::get_component_type_name(type) | |
| 700 | << " (component type not found in map)"; | |
| 701 | ||
| 702 | l.unlock(); | |
| 703 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 704 | "runtime_support::copy_create_component", | |
| 705 | strm.str()); | |
| 706 | return naming::invalid_gid; | |
| 707 | } | |
| 708 | ||
| 709 | if (!(*it).second.first) { | |
| 710 | std::ostringstream strm; | |
| 711 | strm << "attempt to create component instance of " | |
| 712 | << "invalid/unknown type: " | |
| 713 | << components::get_component_type_name(type) | |
| 714 | << " (map entry is nullptr)"; | |
| 715 | ||
| 716 | l.unlock(); | |
| 717 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 718 | "runtime_support::copy_create_component", | |
| 719 | strm.str()); | |
| 720 | return naming::invalid_gid; | |
| 721 | } | |
| 722 | ||
| 723 | naming::gid_type id; | |
| 724 | std::shared_ptr<component_factory_base> factory((*it).second.first); | |
| 725 | { | |
| 726 | util::unlock_guard<std::unique_lock<component_map_mutex_type> > ul(l); | |
| 727 | ||
| 728 | typedef typename Component::wrapping_type wrapping_type; | |
| 729 | if (!local_op) { | |
| 730 | id = factory->create_with_args( | |
| 731 | detail::construct_function<wrapping_type>(std::move(*p))); | |
| 732 | } | |
| 733 | else { | |
| 734 | id = factory->create_with_args( | |
| 735 | detail::construct_function<wrapping_type>(*p)); | |
| 736 | } | |
| 737 | } | |
| 738 | LRT_(info) << "successfully created component " << id | |
| 739 | << " of type: " << components::get_component_type_name(type); | |
| 740 | ||
| 741 | return id; | |
| 742 | } | |
| 743 | ||
| 744 | /////////////////////////////////////////////////////////////////////////// | |
| 745 | template <typename Component> | |
| 746 | naming::gid_type runtime_support::migrate_component_to_here( | |
| 747 | std::shared_ptr<Component> const& p, naming::id_type to_migrate) | |
| 748 | { | |
| 749 | components::component_type const type = | |
| 750 | components::get_component_type< | |
| 751 | typename Component::wrapped_type>(); | |
| 752 | ||
| 753 | std::shared_ptr<component_factory_base> factory; | |
| 754 | naming::gid_type migrated_id; | |
| 755 | ||
| 756 | { | |
| 757 | std::unique_lock<component_map_mutex_type> l(cm_mtx_); | |
| 758 | component_map_type::const_iterator it = components_.find(type); | |
| 759 | if (it == components_.end()) { | |
| 760 | std::ostringstream strm; | |
| 761 | strm << "attempt to migrate component instance of " | |
| 762 | << "invalid/unknown type: " | |
| 763 | << components::get_component_type_name(type) | |
| 764 | << " (component type not found in map)"; | |
| 765 | ||
| 766 | l.unlock(); | |
| 767 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 768 | "runtime_support::migrate_component_to_here", | |
| 769 | strm.str()); | |
| 770 | return naming::invalid_gid; | |
| 771 | } | |
| 772 | ||
| 773 | if (!(*it).second.first) { | |
| 774 | std::ostringstream strm; | |
| 775 | strm << "attempt to migrate component instance of " | |
| 776 | << "invalid/unknown type: " | |
| 777 | << components::get_component_type_name(type) | |
| 778 | << " (map entry is nullptr)"; | |
| 779 | ||
| 780 | l.unlock(); | |
| 781 | HPX_THROW_EXCEPTION(hpx::bad_component_type, | |
| 782 | "runtime_support::migrate_component_to_here", | |
| 783 | strm.str()); | |
| 784 | return naming::invalid_gid; | |
| 785 | } | |
| 786 | ||
| 787 | // create a local instance by copying the bits and remapping the id in | |
| 788 | // AGAS | |
| 789 | migrated_id = to_migrate.get_gid(); | |
| 790 | factory = (*it).second.first; | |
| 791 | } | |
| 792 | ||
| 793 | typedef typename Component::wrapping_type wrapping_type; | |
| 794 | naming::gid_type id = factory->create_with_args(migrated_id, | |
| 795 | detail::construct_function<wrapping_type>(std::move(*p))); | |
| 796 | ||
| 797 | // sanity checks | |
| 798 | if (!id) | |
| 799 | { | |
| 800 | // we should not get here (id should not be invalid) | |
| 801 | HPX_THROW_EXCEPTION(hpx::invalid_status, | |
| 802 | "runtime_support::migrate_component_to_here", | |
| 803 | "could not create copy of given component"); | |
| 804 | return naming::invalid_gid; | |
| 805 | } | |
| 806 | if (id != migrated_id) | |
| 807 | { | |
| 808 | // we should not get here either (the ids should be the same) | |
| 809 | HPX_THROW_EXCEPTION(hpx::invalid_status, | |
| 810 | "runtime_support::migrate_component_to_here", | |
| 811 | "could not create copy of given component (the new id is " | |
| 812 | "different from the original id)"); | |
| 813 | return naming::invalid_gid; | |
| 814 | } | |
| 815 | ||
| 816 | LRT_(info) << "successfully migrated component " << id | |
| 817 | << " of type: " << components::get_component_type_name(type) | |
| 818 | << " to locality: " << find_here(); | |
| 819 | ||
| 820 | // At this point the object has been fully migrated. We now remove | |
| 821 | // the object from the AGAS table of migrated objects. This is | |
| 822 | // necessary as this object might have been migrated off this locality | |
| 823 | // before it was migrated back. | |
| 824 | agas::unmark_as_migrated(id); | |
| 825 | ||
| 826 | to_migrate.make_unmanaged(); | |
| 827 | return id; | |
| 828 | } | |
| 829 | }}} | |
| 830 | ||
| 831 | #include <hpx/config/warnings_suffix.hpp> | |
| 832 | ||
| 833 | HPX_ACTION_USES_LARGE_STACK( | |
| 834 | hpx::components::server::runtime_support::load_components_action) | |
| 835 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 836 | hpx::components::server::runtime_support::call_startup_functions_action) | |
| 837 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 838 | hpx::components::server::runtime_support::call_shutdown_functions_action) | |
| 839 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 840 | hpx::components::server::runtime_support::shutdown_action) | |
| 841 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 842 | hpx::components::server::runtime_support::shutdown_all_action) | |
| 843 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 844 | hpx::components::server::runtime_support::create_performance_counter_action) | |
| 845 | HPX_ACTION_USES_MEDIUM_STACK( | |
| 846 | hpx::components::server::runtime_support::dijkstra_termination_action) | |
| 847 | ||
| 848 | HPX_REGISTER_ACTION_DECLARATION( | |
| 849 | hpx::components::server::runtime_support::bulk_create_components_action, | |
| 850 | bulk_create_components_action) | |
| 851 | HPX_REGISTER_ACTION_DECLARATION( | |
| 852 | hpx::components::server::runtime_support::create_memory_block_action, | |
| 853 | create_memory_block_action) | |
| 854 | HPX_REGISTER_ACTION_DECLARATION( | |
| 855 | hpx::components::server::runtime_support::load_components_action, | |
| 856 | load_components_action) | |
| 857 | HPX_REGISTER_ACTION_DECLARATION( | |
| 858 | hpx::components::server::runtime_support::call_startup_functions_action, | |
| 859 | call_startup_functions_action) | |
| 860 | HPX_REGISTER_ACTION_DECLARATION( | |
| 861 | hpx::components::server::runtime_support::call_shutdown_functions_action, | |
| 862 | call_shutdown_functions_action) | |
| 863 | HPX_REGISTER_ACTION_DECLARATION( | |
| 864 | hpx::components::server::runtime_support::free_component_action, | |
| 865 | free_component_action) | |
| 866 | HPX_REGISTER_ACTION_DECLARATION( | |
| 867 | hpx::components::server::runtime_support::shutdown_action, | |
| 868 | shutdown_action) | |
| 869 | HPX_REGISTER_ACTION_DECLARATION( | |
| 870 | hpx::components::server::runtime_support::shutdown_all_action, | |
| 871 | shutdown_all_action) | |
| 872 | HPX_REGISTER_ACTION_DECLARATION( | |
| 873 | hpx::components::server::runtime_support::terminate_action, | |
| 874 | terminate_action) | |
| 875 | HPX_REGISTER_ACTION_DECLARATION( | |
| 876 | hpx::components::server::runtime_support::terminate_all_action, | |
| 877 | terminate_all_action) | |
| 878 | HPX_REGISTER_ACTION_DECLARATION( | |
| 879 | hpx::components::server::runtime_support::get_config_action, | |
| 880 | get_config_action) | |
| 881 | HPX_REGISTER_ACTION_DECLARATION( | |
| 882 | hpx::components::server::runtime_support::update_agas_cache_entry_action, | |
| 883 | update_agas_cache_entry_action) | |
| 884 | HPX_REGISTER_ACTION_DECLARATION( | |
| 885 | hpx::components::server::runtime_support::garbage_collect_action, | |
| 886 | garbage_collect_action) | |
| 887 | HPX_REGISTER_ACTION_DECLARATION( | |
| 888 | hpx::components::server::runtime_support::create_performance_counter_action, | |
| 889 | create_performance_counter_action) | |
| 890 | HPX_REGISTER_ACTION_DECLARATION( | |
| 891 | hpx::components::server::runtime_support::get_instance_count_action, | |
| 892 | get_instance_count_action) | |
| 893 | HPX_REGISTER_ACTION_DECLARATION( | |
| 894 | hpx::components::server::runtime_support::remove_from_connection_cache_action, | |
| 895 | remove_from_connection_cache_action) | |
| 896 | HPX_REGISTER_ACTION_DECLARATION( | |
| 897 | hpx::components::server::runtime_support::dijkstra_termination_action, | |
| 898 | dijkstra_termination_action) | |
| 899 | ||
| 900 | namespace hpx { namespace components { namespace server | |
| 901 | { | |
| 902 | template <typename Component, typename ...Ts> | |
| 903 | struct create_component_action | |
| 904 | : ::hpx::actions::action< | |
| 905 | naming::gid_type (runtime_support::*)(Ts...) | |
| 906 | , &runtime_support::create_component<Component, Ts...> | |
| 907 | , create_component_action<Component, Ts...> > | |
| 908 | {}; | |
| 909 | ||
| 910 | template <typename Component> | |
| 911 | struct create_component_action<Component> | |
| 912 | : ::hpx::actions::action< | |
| 913 | naming::gid_type (runtime_support::*)() | |
| 914 | , &runtime_support::create_component<Component> | |
| 915 | , create_component_action<Component> > | |
| 916 | {}; | |
| 917 | ||
| 918 | template <typename Component, typename ...Ts> | |
| 919 | struct create_component_direct_action | |
| 920 | : ::hpx::actions::direct_action< | |
| 921 | naming::gid_type (runtime_support::*)(Ts...) | |
| 922 | , &runtime_support::create_component<Component, Ts...> | |
| 923 | , create_component_direct_action<Component, Ts...> > | |
| 924 | {}; | |
| 925 | ||
| 926 | template <typename Component> | |
| 927 | struct create_component_direct_action<Component> | |
| 928 | : ::hpx::actions::direct_action< | |
| 929 | naming::gid_type (runtime_support::*)() | |
| 930 | , &runtime_support::create_component<Component> | |
| 931 | , create_component_direct_action<Component> > | |
| 932 | {}; | |
| 933 | ||
| 934 | /////////////////////////////////////////////////////////////////////////// | |
| 935 | template <typename Component, typename ...Ts> | |
| 936 | struct bulk_create_component_action | |
| 937 | : ::hpx::actions::action< | |
| 938 | std::vector<naming::gid_type> (runtime_support::*)(std::size_t, Ts...) | |
| 939 | , &runtime_support::bulk_create_component<Component, Ts...> | |
| 940 | , bulk_create_component_action<Component, Ts...> > | |
| 941 | {}; | |
| 942 | ||
| 943 | template <typename Component> | |
| 944 | struct bulk_create_component_action<Component> | |
| 945 | : ::hpx::actions::action< | |
| 946 | std::vector<naming::gid_type> (runtime_support::*)(std::size_t) | |
| 947 | , &runtime_support::bulk_create_component<Component> | |
| 948 | , bulk_create_component_action<Component> > | |
| 949 | {}; | |
| 950 | ||
| 951 | template <typename Component, typename ...Ts> | |
| 952 | struct bulk_create_component_direct_action | |
| 953 | : ::hpx::actions::direct_action< | |
| 954 | std::vector<naming::gid_type> (runtime_support::*)(std::size_t, Ts...) | |
| 955 | , &runtime_support::bulk_create_component<Component, Ts...> | |
| 956 | , bulk_create_component_direct_action<Component, Ts...> > | |
| 957 | {}; | |
| 958 | ||
| 959 | template <typename Component> | |
| 960 | struct bulk_create_component_direct_action<Component> | |
| 961 | : ::hpx::actions::direct_action< | |
| 962 | std::vector<naming::gid_type> (runtime_support::*)(std::size_t) | |
| 963 | , &runtime_support::bulk_create_component<Component> | |
| 964 | , bulk_create_component_direct_action<Component> > | |
| 965 | {}; | |
| 966 | ||
| 967 | /////////////////////////////////////////////////////////////////////////// | |
| 968 | template <typename Component> | |
| 969 | struct copy_create_component_action | |
| 970 | : ::hpx::actions::action< | |
| 971 | naming::gid_type (runtime_support::*)( | |
| 972 | std::shared_ptr<Component> const&, bool) | |
| 973 | , &runtime_support::copy_create_component<Component> | |
| 974 | , copy_create_component_action<Component> > | |
| 975 | {}; | |
| 976 | template <typename Component> | |
| 977 | struct migrate_component_here_action | |
| 978 | : ::hpx::actions::action< | |
| 979 | naming::gid_type (runtime_support::*)( | |
| 980 | std::shared_ptr<Component> const&, naming::id_type) | |
| 981 | , &runtime_support::migrate_component_to_here<Component> | |
| 982 | , migrate_component_here_action<Component> > | |
| 983 | {}; | |
| 984 | }}} | |
| 985 | ||
| 986 | namespace hpx { namespace traits | |
| 987 | { | |
| 988 | /////////////////////////////////////////////////////////////////////////// | |
| 989 | // Termination detection does not make this locality black | |
| 990 | template <> | |
| 991 | struct action_does_termination_detection< | |
| 992 | hpx::components::server::runtime_support::dijkstra_termination_action> | |
| 993 | { | |
| 994 | static bool call() | |
| 995 | { | |
| 996 | return true; | |
| 997 | } | |
| 998 | }; | |
| 999 | ||
| 1000 | #if defined(HPX_HAVE_SECURITY) | |
| 1001 | /////////////////////////////////////////////////////////////////////////// | |
| 1002 | // Actions used to create components with constructors of various arities. | |
| 1003 | template <typename Component, typename ...Ts> | |
| 1004 | struct action_capability_provider< | |
| 1005 | components::server::create_component_action<Component, Ts...> > | |
| 1006 | { | |
| 1007 | // return the required capabilities to invoke the given action | |
| 1008 | static components::security::capability call( | |
| 1009 | naming::address::address_type lva) | |
| 1010 | { | |
| 1011 | components::server::runtime_support* rts = | |
| 1012 | get_lva<components::server::runtime_support>::call(lva); | |
| 1013 | ||
| 1014 | components::component_type const type = | |
| 1015 | components::get_component_type< | |
| 1016 | typename Component::wrapped_type>(); | |
| 1017 | return rts->get_factory_capabilities(type); | |
| 1018 | } | |
| 1019 | }; | |
| 1020 | ||
| 1021 | template <typename Component, typename ...Ts> | |
| 1022 | struct action_capability_provider< | |
| 1023 | components::server::create_component_direct_action<Component, Ts...> > | |
| 1024 | { | |
| 1025 | static components::security::capability call( | |
| 1026 | naming::address::address_type lva) | |
| 1027 | { | |
| 1028 | components::server::runtime_support* rts = | |
| 1029 | get_lva<components::server::runtime_support>::call(lva); | |
| 1030 | ||
| 1031 | components::component_type const type = | |
| 1032 | components::get_component_type< | |
| 1033 | typename Component::wrapped_type>(); | |
| 1034 | return rts->get_factory_capabilities(type); | |
| 1035 | } | |
| 1036 | }; | |
| 1037 | #endif | |
| 1038 | ||
| 1039 | // runtime_support is a (hand-rolled) component | |
| 1040 | template <> | |
| 1041 | struct is_component<components::server::runtime_support> | |
| 1042 | : std::true_type | |
| 1043 | {}; | |
| 1044 | }} | |
| 1045 | ||
| 1046 | #endif // HPX_RUNTIME_SUPPORT_JUN_02_2008_1145AM | |
| 1047 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.