1 //  Copyright (c) 2015 Thomas Heller
2 //  Copyright (c) 2018 Hartmut Kaiser
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <hpx/config.hpp>
8 #include <hpx/error_code.hpp>
9 #include <hpx/runtime/agas/interface.hpp>
10 #include <hpx/runtime/applier/applier.hpp>
11 #include <hpx/runtime/applier/bind_naming_wrappers.hpp>
12 #include <hpx/runtime/components/component_type.hpp>
13 #include <hpx/runtime/components/server/component_base.hpp>
14 #include <hpx/runtime/launch_policy.hpp>
15 #include <hpx/runtime/naming/address.hpp>
16 #include <hpx/runtime/naming/name.hpp>
17 #include <hpx/runtime_fwd.hpp>
18 #include <hpx/throw_exception.hpp>
19 #include <hpx/util/assert.hpp>
20 
21 #include <cstdint>
22 #include <mutex>
23 #include <sstream>
24 
25 namespace hpx { namespace components { namespace detail
26 {
~base_component()27     base_component::~base_component()
28     {
29         if (gid_)
30         {
31             error_code ec;
32             agas::unbind(launch::sync, gid_, 1, ec);
33         }
34     }
35 
get_base_gid_dynamic(naming::gid_type const & assign_gid,naming::address const & addr,naming::gid_type (* f)(naming::gid_type)) const36     naming::gid_type base_component::get_base_gid_dynamic(
37         naming::gid_type const& assign_gid, naming::address const& addr,
38         naming::gid_type (*f)(naming::gid_type)) const
39     {
40         if (!gid_)
41         {
42             if (!assign_gid)
43             {
44                 if (f != nullptr)
45                 {
46                     gid_ = f(hpx::detail::get_next_id());
47                 }
48                 else
49                 {
50                     gid_ = hpx::detail::get_next_id();
51                 }
52 
53                 if (!applier::bind_gid_local(gid_, addr))
54                 {
55                     std::ostringstream strm;
56                     strm << "failed to bind id " << gid_
57                             << "to locality: " << hpx::get_locality();
58 
59                     gid_ = naming::invalid_gid;    // invalidate GID
60 
61                     HPX_THROW_EXCEPTION(duplicate_component_address,
62                         "component_base<Component>::get_base_gid",
63                         strm.str());
64                 }
65             }
66             else
67             {
68                 applier::applier& appl = hpx::applier::get_applier();
69                 gid_ = assign_gid;
70                 naming::detail::strip_credits_from_gid(gid_);
71 
72                 if (!agas::bind(
73                         launch::sync, gid_, addr, appl.get_locality_id()))
74                 {
75                     std::ostringstream strm;
76                     strm << "failed to rebind id " << gid_
77                             << "to locality: " << hpx::get_locality();
78 
79                     gid_ = naming::invalid_gid;    // invalidate GID
80 
81                     HPX_THROW_EXCEPTION(duplicate_component_address,
82                         "component_base<Component>::get_base_gid",
83                         strm.str());
84                 }
85             }
86         }
87 
88         std::unique_lock<naming::gid_type::mutex_type> l(gid_.get_mutex());
89 
90         if (!naming::detail::has_credits(gid_))
91         {
92             naming::gid_type gid = gid_;
93             return gid;
94         }
95 
96         // on first invocation take all credits to avoid a self reference
97         naming::gid_type gid = gid_;
98 
99         naming::detail::strip_credits_from_gid(
100             const_cast<naming::gid_type&>(gid_));
101 
102         HPX_ASSERT(naming::detail::has_credits(gid));
103 
104         // We have to assume this credit was split as otherwise the gid
105         // returned at this point will control the lifetime of the
106         // component.
107         naming::detail::set_credit_split_mask_for_gid(gid);
108         return gid;
109     }
110 
get_base_gid(naming::address const & addr,naming::gid_type (* f)(naming::gid_type)) const111     naming::gid_type base_component::get_base_gid(naming::address const& addr,
112         naming::gid_type (*f)(naming::gid_type)) const
113     {
114         if (!gid_)
115         {
116             // generate purely local gid
117             if (f != nullptr)
118             {
119                 gid_ = f(naming::gid_type(addr.address_));
120             }
121             else
122             {
123                 gid_ = naming::gid_type(addr.address_);
124             }
125 
126             naming::detail::set_credit_for_gid(
127                 gid_, std::int64_t(HPX_GLOBALCREDIT_INITIAL));
128             gid_ = naming::replace_component_type(gid_, addr.type_);
129             gid_ = naming::replace_locality_id(gid_, agas::get_locality_id());
130 
131             if (!applier::bind_gid_local(gid_, addr))
132             {
133                 std::ostringstream strm;
134                 strm << "failed to bind id " << gid_
135                         << "to locality: " << hpx::get_locality();
136 
137                 gid_ = naming::invalid_gid;    // invalidate GID
138 
139                 HPX_THROW_EXCEPTION(duplicate_component_address,
140                     "component_base<Component>::get_base_gid",
141                     strm.str());
142             }
143         }
144 
145         std::unique_lock<naming::gid_type::mutex_type> l(gid_.get_mutex());
146 
147         if (!naming::detail::has_credits(gid_))
148         {
149             naming::gid_type gid = gid_;
150             return gid;
151         }
152 
153         // on first invocation take all credits to avoid a self reference
154         naming::gid_type gid = gid_;
155 
156         naming::detail::strip_credits_from_gid(gid_);
157 
158         HPX_ASSERT(naming::detail::has_credits(gid));
159 
160         // We have to assume this credit was split as otherwise the gid
161         // returned at this point will control the lifetime of the
162         // component.
163         naming::detail::set_credit_split_mask_for_gid(gid);
164         return gid;
165     }
166 
get_id(naming::gid_type gid) const167     naming::id_type base_component::get_id(naming::gid_type gid) const
168     {
169         // all credits should have been taken already
170         HPX_ASSERT(!naming::detail::has_credits(gid));
171 
172         // any (subsequent) invocation causes the credits to be replenished
173         naming::detail::replenish_credits(gid);
174         return naming::id_type(gid, naming::id_type::managed);
175     }
176 
get_unmanaged_id(naming::gid_type const & gid) const177     naming::id_type base_component::get_unmanaged_id(
178         naming::gid_type const& gid) const
179     {
180         return naming::id_type(gid, naming::id_type::managed);
181     }
182 }}}
183 
184