/home/users/khuck/src/hpx-lsu/hpx/runtime/components/server/runtime_support.hpp

Line% of fetchesSource
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.