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.