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