1 // Copyright (c) 2007-2018 Hartmut Kaiser 2 // Copyright (c) 2011 Bryce Lelbach 3 // Copyright (c) 2007 Richard D. Guidry Jr. 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 #ifndef HPX_RUNTIME_NAMING_NAME_HPP 9 #define HPX_RUNTIME_NAMING_NAME_HPP 10 11 #include <hpx/config.hpp> 12 #include <hpx/lcos/local/spinlock.hpp> 13 #include <hpx/lcos/local/spinlock_pool.hpp> 14 #include <hpx/runtime/naming/id_type.hpp> 15 #include <hpx/runtime/naming_fwd.hpp> 16 #include <hpx/runtime/serialization/serialization_fwd.hpp> 17 #include <hpx/traits/get_remote_result.hpp> 18 #include <hpx/traits/is_bitwise_serializable.hpp> 19 #include <hpx/traits/promise_local_result.hpp> 20 #include <hpx/util/assert.hpp> 21 #include <hpx/util/atomic_count.hpp> 22 #include <hpx/util/detail/yield_k.hpp> 23 #include <hpx/util/itt_notify.hpp> 24 #include <hpx/util/register_locks.hpp> 25 26 #include <cstddef> 27 #include <cstdint> 28 #include <functional> 29 #include <iosfwd> 30 #include <mutex> 31 #include <string> 32 #include <vector> 33 34 #include <hpx/config/warnings_prefix.hpp> 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // Version of id_type 38 #define HPX_IDTYPE_VERSION 0x20 39 #define HPX_GIDTYPE_VERSION 0x10 40 41 /////////////////////////////////////////////////////////////////////////////// 42 namespace hpx { namespace naming 43 { 44 namespace detail 45 { 46 /////////////////////////////////////////////////////////////////////// 47 // forward declaration 48 inline std::uint64_t strip_internal_bits_from_gid(std::uint64_t msb) 49 HPX_SUPER_PURE; 50 51 inline std::uint64_t strip_internal_bits_and_component_type_from_gid( 52 std::uint64_t msb) HPX_SUPER_PURE; 53 54 inline std::uint64_t strip_lock_from_gid(std::uint64_t msb) 55 HPX_SUPER_PURE; 56 57 inline std::uint64_t get_internal_bits(std::uint64_t msb) 58 HPX_SUPER_PURE; 59 60 inline std::uint64_t strip_internal_bits_and_locality_from_gid( 61 std::uint64_t msb) HPX_SUPER_PURE; 62 63 inline bool is_locked(gid_type const& gid); 64 } 65 66 /////////////////////////////////////////////////////////////////////////// 67 /// Global identifier for components across the HPX system. 68 struct HPX_EXPORT gid_type 69 { 70 struct tag {}; 71 72 // These typedefs are for Boost.ICL. 73 typedef gid_type size_type; 74 typedef gid_type difference_type; 75 76 static std::uint64_t const credit_base_mask = 0x1full; 77 static std::uint16_t const credit_shift = 24; 78 79 static std::uint64_t const credit_mask = credit_base_mask << credit_shift; 80 static std::uint64_t const was_split_mask = 0x80000000ull; //-V112 81 static std::uint64_t const has_credits_mask = 0x40000000ull; //-V112 82 static std::uint64_t const is_locked_mask = 0x20000000ull; //-V112 83 84 static std::uint64_t const locality_id_mask = 0xffffffff00000000ull; 85 static std::uint16_t const locality_id_shift = 32; //-V112 86 87 static std::uint64_t const virtual_memory_mask = 0x3fffffull; 88 89 // don't cache this id in the AGAS caches 90 static std::uint64_t const dont_cache_mask = 0x800000ull; //-V112 91 92 // the object is migratable 93 static std::uint64_t const is_migratable = 0x400000ull; //-V112 94 95 // Bit 64 is set for all dynamically assigned ids (if this is not set 96 // then the lsb corresponds to the lva of the referenced object). 97 static std::uint64_t const dynamically_assigned = 0x1ull; 98 99 // Bits 65-84 are used to store the component type (20 bits) if bit 100 // 64 is not set. 101 static std::uint64_t const component_type_base_mask = 0xfffffull; 102 static std::uint64_t const component_type_shift = 1ull; 103 static std::uint64_t const component_type_mask = 104 component_type_base_mask << component_type_shift; 105 106 static std::uint64_t const credit_bits_mask = 107 credit_mask | was_split_mask | has_credits_mask; 108 static std::uint64_t const internal_bits_mask = credit_bits_mask | 109 is_locked_mask | dont_cache_mask | is_migratable; 110 static std::uint64_t const special_bits_mask = 111 locality_id_mask | internal_bits_mask | component_type_mask; 112 gid_typehpx::naming::gid_type113 explicit gid_type (std::uint64_t lsb_id = 0) 114 : id_msb_(0), id_lsb_(lsb_id) 115 {} 116 gid_typehpx::naming::gid_type117 explicit gid_type (std::uint64_t msb_id, std::uint64_t lsb_id) 118 : id_msb_(naming::detail::strip_lock_from_gid(msb_id)), 119 id_lsb_(lsb_id) 120 { 121 } 122 gid_typehpx::naming::gid_type123 gid_type (gid_type const& rhs) 124 : id_msb_(naming::detail::strip_lock_from_gid(rhs.get_msb())), 125 id_lsb_(rhs.get_lsb()) 126 { 127 } gid_typehpx::naming::gid_type128 gid_type (gid_type && rhs) 129 : id_msb_(naming::detail::strip_lock_from_gid(rhs.get_msb())), 130 id_lsb_(rhs.get_lsb()) 131 { 132 rhs.id_lsb_ = rhs.id_msb_ = 0; 133 } 134 ~gid_typehpx::naming::gid_type135 ~gid_type() 136 { 137 HPX_ASSERT(!is_locked()); 138 } 139 operator =hpx::naming::gid_type140 gid_type& operator=(std::uint64_t lsb_id) 141 { 142 HPX_ASSERT(!is_locked()); 143 id_msb_ = 0; 144 id_lsb_ = lsb_id; 145 return *this; 146 } 147 operator =hpx::naming::gid_type148 gid_type& operator=(gid_type const& rhs) 149 { 150 if (this != &rhs) 151 { 152 HPX_ASSERT(!is_locked()); 153 id_msb_ = naming::detail::strip_lock_from_gid(rhs.get_msb()); 154 id_lsb_ = rhs.get_lsb(); 155 } 156 return *this; 157 } operator =hpx::naming::gid_type158 gid_type& operator=(gid_type && rhs) 159 { 160 if (this != &rhs) 161 { 162 HPX_ASSERT(!is_locked()); 163 id_msb_ = naming::detail::strip_lock_from_gid(rhs.get_msb()); 164 id_lsb_ = rhs.get_lsb(); 165 166 rhs.id_lsb_ = rhs.id_msb_ = 0; 167 } 168 return *this; 169 } 170 operator boolhpx::naming::gid_type171 explicit operator bool() const noexcept 172 { 173 return 0 != id_lsb_ || 0 != id_msb_; 174 } 175 176 // We support increment, decrement, addition and subtraction operator ++hpx::naming::gid_type177 gid_type& operator++() // pre-increment 178 { 179 *this += 1; 180 return *this; 181 } operator ++hpx::naming::gid_type182 gid_type operator++(int) // post-increment 183 { 184 gid_type t(*this); 185 ++(*this); 186 return t; 187 } 188 operator --hpx::naming::gid_type189 gid_type& operator--() // pre-decrement 190 { 191 *this -= 1; 192 return *this; 193 } operator --hpx::naming::gid_type194 gid_type operator--(int) // post-decrement 195 { 196 gid_type t(*this); 197 --(*this); 198 return t; 199 } 200 201 // GID + GID 202 friend HPX_EXPORT gid_type operator+ ( 203 gid_type const& lhs, gid_type const& rhs); operator +=hpx::naming::gid_type204 gid_type operator+= (gid_type const& rhs) 205 { return (*this = *this + rhs); } 206 207 // GID + std::uint64_t operator +(gid_type const & lhs,std::uint64_t rhs)208 friend gid_type operator+ (gid_type const& lhs, std::uint64_t rhs) 209 { return lhs + gid_type(0, rhs); } operator +=hpx::naming::gid_type210 gid_type operator+= (std::uint64_t rhs) 211 { return (*this = *this + rhs); } 212 213 // GID - GID 214 friend HPX_EXPORT gid_type operator- (gid_type const& lhs, 215 gid_type const& rhs); operator -=hpx::naming::gid_type216 gid_type operator-= (gid_type const& rhs) 217 { return (*this = *this - rhs); } 218 219 // GID - std::uint64_t operator -(gid_type const & lhs,std::uint64_t rhs)220 friend gid_type operator- (gid_type const& lhs, std::uint64_t rhs) 221 { return lhs - gid_type(0, rhs); } operator -=hpx::naming::gid_type222 gid_type operator-= (std::uint64_t rhs) 223 { return (*this = *this - rhs); } 224 operator &(gid_type const & lhs,std::uint64_t rhs)225 friend gid_type operator& (gid_type const& lhs, std::uint64_t rhs) 226 { 227 return gid_type(lhs.id_msb_, lhs.id_lsb_ & rhs); 228 } 229 230 // comparison is required as well operator ==(gid_type const & lhs,gid_type const & rhs)231 friend bool operator== (gid_type const& lhs, gid_type const& rhs) 232 { 233 std::int64_t lhs_msb = 234 detail::strip_internal_bits_from_gid(lhs.id_msb_); 235 std::int64_t rhs_msb = 236 detail::strip_internal_bits_from_gid(rhs.id_msb_); 237 238 return (lhs_msb == rhs_msb) && (lhs.id_lsb_ == rhs.id_lsb_); 239 } operator !=(gid_type const & lhs,gid_type const & rhs)240 friend bool operator!= (gid_type const& lhs, gid_type const& rhs) 241 { 242 return !(lhs == rhs); 243 } 244 operator <(gid_type const & lhs,gid_type const & rhs)245 friend bool operator< (gid_type const& lhs, gid_type const& rhs) 246 { 247 std::int64_t lhs_msb = 248 detail::strip_internal_bits_from_gid(lhs.id_msb_); 249 std::int64_t rhs_msb = 250 detail::strip_internal_bits_from_gid(rhs.id_msb_); 251 252 if (lhs_msb < rhs_msb) 253 { 254 return true; 255 } 256 if (lhs_msb > rhs_msb) 257 { 258 return false; 259 } 260 return lhs.id_lsb_ < rhs.id_lsb_; 261 } 262 operator <=(gid_type const & lhs,gid_type const & rhs)263 friend bool operator<= (gid_type const& lhs, gid_type const& rhs) 264 { 265 std::int64_t lhs_msb = 266 detail::strip_internal_bits_from_gid(lhs.id_msb_); 267 std::int64_t rhs_msb = 268 detail::strip_internal_bits_from_gid(rhs.id_msb_); 269 270 if (lhs_msb < rhs_msb) 271 { 272 return true; 273 } 274 if (lhs_msb > rhs_msb) 275 { 276 return false; 277 } 278 return lhs.id_lsb_ <= rhs.id_lsb_; 279 } 280 operator >(gid_type const & lhs,gid_type const & rhs)281 friend bool operator> (gid_type const& lhs, gid_type const& rhs) 282 { 283 return !(lhs <= rhs); 284 } 285 operator >=(gid_type const & lhs,gid_type const & rhs)286 friend bool operator>= (gid_type const& lhs, gid_type const& rhs) 287 { 288 return !(lhs < rhs); 289 } 290 get_msbhpx::naming::gid_type291 std::uint64_t get_msb() const 292 { 293 return id_msb_; 294 } set_msbhpx::naming::gid_type295 void set_msb(std::uint64_t msb) 296 { 297 id_msb_ = msb; 298 } get_lsbhpx::naming::gid_type299 std::uint64_t get_lsb() const 300 { 301 return id_lsb_; 302 } set_lsbhpx::naming::gid_type303 void set_lsb(std::uint64_t lsb) 304 { 305 id_lsb_ = lsb; 306 } set_lsbhpx::naming::gid_type307 void set_lsb(void* lsb) 308 { 309 id_lsb_ = reinterpret_cast<std::uint64_t>(lsb); 310 } 311 312 std::string to_string() const; 313 314 // this type is at the same time its own mutex type 315 typedef gid_type mutex_type; 316 317 // Note: we deliberately don't register this lock with the lock 318 // tracking to avoid false positives. We know that gid_types need 319 // to be locked while suspension. lockhpx::naming::gid_type320 void lock() 321 { 322 HPX_ITT_SYNC_PREPARE(this); 323 324 for (std::size_t k = 0; !acquire_lock(); ++k) 325 { 326 util::detail::yield_k(k, "hpx::naming::gid_type::lock"); 327 } 328 329 util::register_lock(this); 330 331 HPX_ITT_SYNC_ACQUIRED(this); 332 } 333 try_lockhpx::naming::gid_type334 bool try_lock() 335 { 336 HPX_ITT_SYNC_PREPARE(this); 337 338 if (acquire_lock()) 339 { 340 HPX_ITT_SYNC_ACQUIRED(this); 341 util::register_lock(this); 342 return true; 343 } 344 345 HPX_ITT_SYNC_CANCEL(this); 346 return false; 347 } 348 unlockhpx::naming::gid_type349 void unlock() 350 { 351 HPX_ITT_SYNC_RELEASING(this); 352 353 relinquish_lock(); 354 util::unregister_lock(this); 355 356 HPX_ITT_SYNC_RELEASED(this); 357 } 358 get_mutexhpx::naming::gid_type359 mutex_type& get_mutex() const { return const_cast<mutex_type&>(*this); } 360 361 private: 362 friend HPX_EXPORT std::ostream& operator<<(std::ostream& os, 363 gid_type const& id); 364 365 friend class hpx::serialization::access; 366 367 void save(serialization::output_archive& ar, unsigned int version) const; 368 369 void load(serialization::input_archive& ar, unsigned int version); 370 371 HPX_SERIALIZATION_SPLIT_MEMBER() 372 373 // lock implementation 374 typedef lcos::local::spinlock_pool<tag> internal_mutex_type; 375 376 // returns whether lock has been acquired acquire_lockhpx::naming::gid_type377 bool acquire_lock() 378 { 379 internal_mutex_type::scoped_lock l(this); 380 bool was_locked = (id_msb_ & is_locked_mask) ? true : false; 381 if (!was_locked) 382 { 383 id_msb_ |= is_locked_mask; 384 return true; 385 } 386 return false; 387 } 388 relinquish_lockhpx::naming::gid_type389 void relinquish_lock() 390 { 391 util::ignore_lock(this); 392 internal_mutex_type::scoped_lock l(this); 393 util::reset_ignored(this); 394 395 id_msb_ &= ~is_locked_mask; 396 } 397 398 // this is used for assertions only, no need to acquire the lock is_lockedhpx::naming::gid_type399 bool is_locked() const 400 { 401 return (id_msb_ & is_locked_mask) ? true : false; 402 } 403 404 friend bool detail::is_locked(gid_type const& gid); 405 406 // actual gid 407 std::uint64_t id_msb_; 408 std::uint64_t id_lsb_; 409 }; 410 }} 411 412 /////////////////////////////////////////////////////////////////////////////// 413 // we know that we can serialize a gid as a byte sequence 414 HPX_IS_BITWISE_SERIALIZABLE(hpx::naming::gid_type) 415 416 namespace hpx { namespace naming 417 { 418 /////////////////////////////////////////////////////////////////////////// 419 // Handle conversion to/from locality_id 420 inline gid_type get_gid_from_locality_id(std::uint32_t locality_id) 421 HPX_SUPER_PURE; 422 get_gid_from_locality_id(std::uint32_t locality_id)423 inline gid_type get_gid_from_locality_id(std::uint32_t locality_id) 424 { 425 return gid_type( 426 std::uint64_t(locality_id+1) << gid_type::locality_id_shift, 427 0); 428 } 429 430 inline std::uint32_t get_locality_id_from_gid(std::uint64_t msb) HPX_PURE; 431 get_locality_id_from_gid(std::uint64_t msb)432 inline std::uint32_t get_locality_id_from_gid(std::uint64_t msb) 433 { 434 return std::uint32_t(msb >> gid_type::locality_id_shift) - 1; 435 } 436 437 inline std::uint32_t get_locality_id_from_gid(gid_type const& id) HPX_PURE; 438 get_locality_id_from_gid(gid_type const & id)439 inline std::uint32_t get_locality_id_from_gid(gid_type const& id) 440 { 441 return get_locality_id_from_gid(id.get_msb()); 442 } 443 get_locality_from_gid(gid_type const & id)444 inline gid_type get_locality_from_gid(gid_type const& id) 445 { 446 return get_gid_from_locality_id(get_locality_id_from_gid(id)); 447 } 448 is_locality(gid_type const & gid)449 inline bool is_locality(gid_type const& gid) 450 { 451 return get_locality_from_gid(gid) == gid; 452 } 453 454 inline std::uint64_t replace_locality_id(std::uint64_t msb, 455 std::uint32_t locality_id) HPX_PURE; 456 replace_locality_id(std::uint64_t msb,std::uint32_t locality_id)457 inline std::uint64_t replace_locality_id(std::uint64_t msb, 458 std::uint32_t locality_id) 459 { 460 msb &= ~gid_type::locality_id_mask; 461 return msb | get_gid_from_locality_id(locality_id).get_msb(); 462 } 463 464 inline gid_type replace_locality_id(gid_type const& gid, 465 std::uint32_t locality_id) HPX_PURE; 466 replace_locality_id(gid_type const & gid,std::uint32_t locality_id)467 inline gid_type replace_locality_id(gid_type const& gid, 468 std::uint32_t locality_id) 469 { 470 std::uint64_t msb = gid.get_msb() & ~gid_type::locality_id_mask; 471 msb |= get_gid_from_locality_id(locality_id).get_msb(); 472 return gid_type(msb, gid.get_lsb()); 473 } 474 475 /////////////////////////////////////////////////////////////////////////// refers_to_virtual_memory(std::uint64_t msb)476 inline bool refers_to_virtual_memory(std::uint64_t msb) 477 { 478 return !(msb & gid_type::virtual_memory_mask); 479 } 480 refers_to_virtual_memory(gid_type const & gid)481 inline bool refers_to_virtual_memory(gid_type const& gid) 482 { 483 return refers_to_virtual_memory(gid.get_msb()); 484 } 485 486 /////////////////////////////////////////////////////////////////////////// refers_to_local_lva(gid_type const & gid)487 inline bool refers_to_local_lva(gid_type const& gid) 488 { 489 return !(gid.get_msb() & gid_type::dynamically_assigned); 490 } 491 replace_component_type(gid_type const & gid,std::uint32_t type)492 inline gid_type replace_component_type(gid_type const& gid, 493 std::uint32_t type) 494 { 495 std::uint64_t msb = gid.get_msb() & ~gid_type::component_type_mask; 496 497 HPX_ASSERT(!(msb & gid_type::dynamically_assigned)); 498 msb |= ((type << gid_type::component_type_shift) & 499 gid_type::component_type_mask); 500 return gid_type(msb, gid.get_lsb()); 501 } 502 503 /////////////////////////////////////////////////////////////////////////// 504 namespace detail 505 { 506 // We store the log2(credit) in the gid_type log2(std::int64_t val)507 inline std::int16_t log2(std::int64_t val) 508 { 509 std::int16_t ret = -1; 510 while (val != 0) 511 { 512 val >>= 1; 513 ++ret; 514 } 515 return ret; 516 } 517 power2(std::int16_t log2credits)518 inline std::int64_t power2(std::int16_t log2credits) 519 { 520 HPX_ASSERT(log2credits >= 0); 521 return static_cast<std::int64_t>(1) << log2credits; 522 } 523 524 /////////////////////////////////////////////////////////////////////// has_credits(gid_type const & id)525 inline bool has_credits(gid_type const& id) 526 { 527 return (id.get_msb() & gid_type::has_credits_mask) ? true : false; 528 } 529 gid_was_split(gid_type const & id)530 inline bool gid_was_split(gid_type const& id) 531 { 532 return (id.get_msb() & gid_type::was_split_mask) ? true : false; 533 } 534 set_credit_split_mask_for_gid(gid_type & id)535 inline void set_credit_split_mask_for_gid(gid_type& id) 536 { 537 id.set_msb(id.get_msb() | gid_type::was_split_mask); 538 } 539 540 /////////////////////////////////////////////////////////////////////// store_in_cache(gid_type const & id)541 inline bool store_in_cache(gid_type const& id) 542 { 543 return (id.get_msb() & gid_type::dont_cache_mask) ? false : true; 544 } 545 set_dont_store_in_cache(gid_type & gid)546 inline void set_dont_store_in_cache(gid_type& gid) 547 { 548 gid.set_msb(gid.get_msb() | gid_type::dont_cache_mask); 549 } 550 set_dont_store_in_cache(id_type & id)551 inline void set_dont_store_in_cache(id_type& id) 552 { 553 id.set_msb(id.get_msb() | gid_type::dont_cache_mask); 554 } 555 556 /////////////////////////////////////////////////////////////////////// is_migratable(gid_type const & id)557 inline bool is_migratable(gid_type const& id) 558 { 559 return (id.get_msb() & gid_type::is_migratable) ? true : false; 560 } 561 set_is_migratable(gid_type & gid)562 inline void set_is_migratable(gid_type& gid) 563 { 564 gid.set_msb(gid.get_msb() | gid_type::is_migratable); 565 } 566 567 /////////////////////////////////////////////////////////////////////// 568 inline std::int64_t get_credit_from_gid(gid_type const& id) HPX_PURE; 569 get_log2credit_from_gid(gid_type const & id)570 inline std::int16_t get_log2credit_from_gid(gid_type const& id) 571 { 572 HPX_ASSERT(has_credits(id)); 573 return std::int16_t((id.get_msb() >> gid_type::credit_shift) & 574 gid_type::credit_base_mask); 575 } 576 get_credit_from_gid(gid_type const & id)577 inline std::int64_t get_credit_from_gid(gid_type const& id) 578 { 579 return has_credits(id) ? detail::power2(get_log2credit_from_gid(id)) : 0; 580 } 581 582 /////////////////////////////////////////////////////////////////////// strip_internal_bits_from_gid(std::uint64_t msb)583 inline std::uint64_t strip_internal_bits_from_gid(std::uint64_t msb) 584 { 585 return msb & ~gid_type::internal_bits_mask; 586 } 587 strip_internal_bits_from_gid(gid_type & id)588 inline gid_type& strip_internal_bits_from_gid(gid_type& id) 589 { 590 id.set_msb(strip_internal_bits_from_gid(id.get_msb())); 591 return id; 592 } 593 strip_internal_bits_except_dont_cache_from_gid(std::uint64_t msb)594 inline std::uint64_t strip_internal_bits_except_dont_cache_from_gid( 595 std::uint64_t msb) 596 { 597 return msb & ~(gid_type::credit_bits_mask | gid_type::is_locked_mask); 598 } 599 strip_internal_bits_except_dont_cache_from_gid(gid_type & id)600 inline gid_type& strip_internal_bits_except_dont_cache_from_gid( 601 gid_type& id) 602 { 603 id.set_msb( 604 strip_internal_bits_except_dont_cache_from_gid(id.get_msb())); 605 return id; 606 } 607 strip_internal_bits_and_component_type_from_gid(std::uint64_t msb)608 inline std::uint64_t strip_internal_bits_and_component_type_from_gid( 609 std::uint64_t msb) 610 { 611 return msb & 612 ~(gid_type::internal_bits_mask | gid_type::component_type_mask); 613 } 614 strip_internal_bits_and_component_type_from_gid(gid_type & id)615 inline gid_type& strip_internal_bits_and_component_type_from_gid( 616 gid_type& id) 617 { 618 id.set_msb( 619 strip_internal_bits_and_component_type_from_gid(id.get_msb())); 620 return id; 621 } 622 get_internal_bits(std::uint64_t msb)623 inline std::uint64_t get_internal_bits(std::uint64_t msb) 624 { 625 return msb & 626 (gid_type::internal_bits_mask | gid_type::component_type_mask); 627 } 628 strip_internal_bits_and_locality_from_gid(std::uint64_t msb)629 inline std::uint64_t strip_internal_bits_and_locality_from_gid( 630 std::uint64_t msb) 631 { 632 return msb & 633 (~gid_type::special_bits_mask | gid_type::component_type_mask); 634 } 635 636 /////////////////////////////////////////////////////////////////////// get_component_type_from_gid(std::uint64_t msb)637 inline std::uint32_t get_component_type_from_gid(std::uint64_t msb) 638 { 639 HPX_ASSERT(!(msb & gid_type::dynamically_assigned)); 640 return (msb >> gid_type::component_type_shift) & 641 gid_type::component_type_base_mask; 642 } 643 add_component_type_to_gid(std::uint64_t msb,std::uint32_t type)644 inline std::uint64_t add_component_type_to_gid(std::uint64_t msb, 645 std::uint32_t type) 646 { 647 HPX_ASSERT(!(msb & gid_type::dynamically_assigned)); 648 return (msb & ~gid_type::component_type_mask) | 649 ((type << gid_type::component_type_shift) & 650 gid_type::component_type_mask); 651 } 652 653 /////////////////////////////////////////////////////////////////////// strip_lock_from_gid(std::uint64_t msb)654 inline std::uint64_t strip_lock_from_gid(std::uint64_t msb) 655 { 656 return msb & ~gid_type::is_locked_mask; 657 } 658 strip_lock_from_gid(gid_type & gid)659 inline gid_type& strip_lock_from_gid(gid_type& gid) 660 { 661 gid.set_msb(strip_lock_from_gid(gid.get_msb())); 662 return gid; 663 } 664 is_locked(gid_type const & gid)665 inline bool is_locked(gid_type const& gid) 666 { 667 return gid.is_locked(); 668 } 669 670 /////////////////////////////////////////////////////////////////////// 671 inline gid_type get_stripped_gid(gid_type const& id) HPX_PURE; 672 get_stripped_gid(gid_type const & id)673 inline gid_type get_stripped_gid(gid_type const& id) 674 { 675 std::uint64_t const msb = strip_internal_bits_from_gid(id.get_msb()); 676 std::uint64_t const lsb = id.get_lsb(); 677 return gid_type(msb, lsb); 678 } 679 680 inline gid_type get_stripped_gid_except_dont_cache(gid_type const& id) 681 HPX_PURE; 682 get_stripped_gid_except_dont_cache(gid_type const & id)683 inline gid_type get_stripped_gid_except_dont_cache(gid_type const& id) 684 { 685 std::uint64_t const msb = 686 strip_internal_bits_except_dont_cache_from_gid(id.get_msb()); 687 std::uint64_t const lsb = id.get_lsb(); 688 return gid_type(msb, lsb); 689 } 690 strip_credits_from_gid(std::uint64_t msb)691 inline std::uint64_t strip_credits_from_gid(std::uint64_t msb) 692 { 693 return msb & ~gid_type::credit_bits_mask; 694 } 695 strip_credits_from_gid(gid_type & id)696 inline gid_type& strip_credits_from_gid(gid_type& id) 697 { 698 id.set_msb(strip_credits_from_gid(id.get_msb())); 699 return id; 700 } 701 702 /////////////////////////////////////////////////////////////////////// set_log2credit_for_gid(gid_type & id,std::int16_t log2credits)703 inline void set_log2credit_for_gid(gid_type& id, std::int16_t log2credits) 704 { 705 // credit should be a clean log2 706 HPX_ASSERT(log2credits >= 0); 707 HPX_ASSERT(0 == (log2credits & ~gid_type::credit_base_mask)); 708 709 id.set_msb((id.get_msb() & ~gid_type::credit_mask) | 710 ((std::int32_t(log2credits) << gid_type::credit_shift) 711 & gid_type::credit_mask) | 712 gid_type::has_credits_mask); 713 } 714 set_credit_for_gid(gid_type & id,std::int64_t credits)715 inline void set_credit_for_gid(gid_type& id, std::int64_t credits) 716 { 717 if (credits != 0) 718 { 719 std::int16_t log2credits = detail::log2(credits); 720 HPX_ASSERT(detail::power2(log2credits) == credits); 721 722 set_log2credit_for_gid(id, log2credits); 723 } 724 else 725 { 726 strip_credits_from_gid(id); 727 } 728 } 729 730 /////////////////////////////////////////////////////////////////////// 731 // has side effects, can't be pure 732 HPX_EXPORT std::int64_t add_credit_to_gid(gid_type& id, 733 std::int64_t credits); 734 735 HPX_EXPORT std::int64_t remove_credit_from_gid(gid_type& id, 736 std::int64_t debit); 737 738 HPX_EXPORT std::int64_t fill_credit_for_gid(gid_type& id, 739 std::int64_t credits = std::int64_t(HPX_GLOBALCREDIT_INITIAL)); 740 741 /////////////////////////////////////////////////////////////////////// 742 HPX_EXPORT gid_type move_gid(gid_type& id); 743 HPX_EXPORT gid_type move_gid_locked(std::unique_lock<gid_type::mutex_type> l, 744 gid_type& gid); 745 746 HPX_EXPORT std::int64_t replenish_credits(gid_type& id); 747 HPX_EXPORT std::int64_t replenish_credits_locked( 748 std::unique_lock<gid_type::mutex_type>& l, gid_type& id); 749 750 /////////////////////////////////////////////////////////////////////// 751 // splits the current credit of the given id and assigns half of it to 752 // the returned copy 753 HPX_EXPORT gid_type split_credits_for_gid(gid_type& id); 754 HPX_EXPORT gid_type split_credits_for_gid_locked( 755 std::unique_lock<gid_type::mutex_type>& l, gid_type& id); 756 } 757 758 HPX_EXPORT gid_type operator+ (gid_type const& lhs, gid_type const& rhs); 759 HPX_EXPORT gid_type operator- (gid_type const& lhs, gid_type const& rhs); 760 761 /////////////////////////////////////////////////////////////////////////// 762 gid_type const invalid_gid = gid_type(); 763 764 /////////////////////////////////////////////////////////////////////////// 765 HPX_EXPORT std::ostream& operator<<(std::ostream& os, gid_type const& id); 766 767 namespace detail 768 { 769 /////////////////////////////////////////////////////////////////////// 770 enum id_type_management 771 { 772 unknown_deleter = -1, 773 unmanaged = 0, // unmanaged GID 774 managed = 1, // managed GID 775 managed_move_credit = 2 // managed GID which will give up all 776 // credits when sent 777 }; 778 779 // forward declaration 780 struct HPX_EXPORT id_type_impl; 781 782 // custom deleter for id_type_impl above 783 HPX_EXPORT void gid_managed_deleter (id_type_impl* p); 784 HPX_EXPORT void gid_unmanaged_deleter (id_type_impl* p); 785 786 HPX_EXPORT void intrusive_ptr_add_ref(id_type_impl* p); 787 HPX_EXPORT void intrusive_ptr_release(id_type_impl* p); 788 789 /////////////////////////////////////////////////////////////////////// 790 struct HPX_EXPORT id_type_impl : gid_type 791 { 792 public: 793 HPX_NON_COPYABLE(id_type_impl); 794 795 private: 796 typedef void (*deleter_type)(detail::id_type_impl*); 797 static deleter_type get_deleter(id_type_management t); 798 799 public: id_type_implhpx::naming::detail::id_type_impl800 id_type_impl() 801 : count_(0), type_(unknown_deleter) 802 {} 803 id_type_implhpx::naming::detail::id_type_impl804 explicit id_type_impl (std::uint64_t lsb_id, id_type_management t) 805 : gid_type(0, lsb_id), count_(0), type_(t) 806 {} 807 id_type_implhpx::naming::detail::id_type_impl808 explicit id_type_impl (std::uint64_t msb_id, std::uint64_t lsb_id, 809 id_type_management t) 810 : gid_type(msb_id, lsb_id), count_(0), type_(t) 811 {} 812 id_type_implhpx::naming::detail::id_type_impl813 explicit id_type_impl (gid_type const& gid, id_type_management t) 814 : gid_type(gid), count_(0), type_(t) 815 {} 816 get_management_typehpx::naming::detail::id_type_impl817 id_type_management get_management_type() const 818 { 819 return type_; 820 } set_management_typehpx::naming::detail::id_type_impl821 void set_management_type(id_type_management type) 822 { 823 type_ = type; 824 } 825 826 // serialization 827 void save(serialization::output_archive& ar, unsigned) const; 828 829 void load(serialization::input_archive& ar, unsigned); 830 831 HPX_SERIALIZATION_SPLIT_MEMBER() 832 833 private: 834 // credit management (called during serialization), this function 835 // has to be 'const' as save() above has to be 'const'. 836 void preprocess_gid(serialization::output_archive& ar) const; 837 838 // reference counting 839 friend HPX_EXPORT void intrusive_ptr_add_ref(id_type_impl* p); 840 friend HPX_EXPORT void intrusive_ptr_release(id_type_impl* p); 841 842 util::atomic_count count_; 843 id_type_management type_; 844 }; 845 } 846 847 /////////////////////////////////////////////////////////////////////////// 848 HPX_API_EXPORT gid_type get_parcel_dest_gid(id_type const& id); 849 }} 850 851 #include <hpx/runtime/naming/id_type.hpp> 852 #include <hpx/runtime/naming/id_type_impl.hpp> 853 854 namespace hpx { namespace naming 855 { 856 /////////////////////////////////////////////////////////////////////////// 857 HPX_EXPORT std::ostream& operator<<(std::ostream& os, id_type const& id); 858 859 /////////////////////////////////////////////////////////////////////// 860 // Handle conversion to/from locality_id 861 // FIXME: these names are confusing, 'id' appears in identifiers far too 862 // frequently. 863 inline id_type get_id_from_locality_id(std::uint32_t locality_id) HPX_SUPER_PURE; 864 get_id_from_locality_id(std::uint32_t locality_id)865 inline id_type get_id_from_locality_id(std::uint32_t locality_id) 866 { 867 return id_type( 868 std::uint64_t(locality_id+1) << gid_type::locality_id_shift, 869 0, id_type::unmanaged); 870 } 871 872 inline std::uint32_t get_locality_id_from_id(id_type const& id) HPX_PURE; 873 get_locality_id_from_id(id_type const & id)874 inline std::uint32_t get_locality_id_from_id(id_type const& id) 875 { 876 return std::uint32_t(id.get_msb() >> gid_type::locality_id_shift) - 1; 877 } 878 get_locality_from_id(id_type const & id)879 inline id_type get_locality_from_id(id_type const& id) 880 { 881 return get_id_from_locality_id(get_locality_id_from_id(id)); 882 } 883 is_locality(id_type const & id)884 inline bool is_locality(id_type const& id) 885 { 886 return is_locality(id.get_gid()); 887 } 888 889 /////////////////////////////////////////////////////////////////////////// 890 HPX_EXPORT char const* get_management_type_name(id_type::management_type m); 891 }} 892 893 /////////////////////////////////////////////////////////////////////////////// 894 namespace hpx { namespace traits 895 { 896 template <> 897 struct get_remote_result<naming::id_type, naming::gid_type> 898 { callhpx::traits::get_remote_result899 static naming::id_type call(naming::gid_type const& rhs) 900 { 901 bool has_credits = naming::detail::has_credits(rhs); 902 return naming::id_type(rhs, 903 has_credits ? 904 naming::id_type::managed : 905 naming::id_type::unmanaged); 906 } 907 }; 908 909 template <> 910 struct promise_local_result<naming::gid_type> 911 { 912 typedef naming::id_type type; 913 }; 914 915 // we need to specialize this template to allow for automatic conversion of 916 // the vector<naming::gid_type> to a vector<naming::id_type> 917 template <> 918 struct get_remote_result< 919 std::vector<naming::id_type>, std::vector<naming::gid_type> > 920 { 921 static std::vector<naming::id_type> callhpx::traits::get_remote_result922 call(std::vector<naming::gid_type> const& rhs) 923 { 924 std::vector<naming::id_type> result; 925 result.reserve(rhs.size()); 926 for (naming::gid_type const& r : rhs) 927 { 928 bool has_credits = naming::detail::has_credits(r); 929 result.push_back(naming::id_type(r, 930 has_credits ? 931 naming::id_type::managed : 932 naming::id_type::unmanaged)); 933 } 934 return result; 935 } 936 }; 937 938 template <> 939 struct promise_local_result<std::vector<naming::gid_type> > 940 { 941 typedef std::vector<naming::id_type> type; 942 }; 943 }} 944 945 /////////////////////////////////////////////////////////////////////////////// 946 namespace hpx 947 { 948 // pull invalid id into the main namespace 949 using naming::invalid_id; 950 } 951 952 /////////////////////////////////////////////////////////////////////////////// 953 namespace std 954 { 955 // specialize std::hash for hpx::naming::gid_type 956 template <> 957 struct hash<hpx::naming::gid_type> 958 { operator ()std::hash959 std::size_t operator()(::hpx::naming::gid_type const& gid) const 960 { 961 std::size_t const h1 (std::hash<std::uint64_t>()(gid.get_lsb())); 962 std::size_t const h2 (std::hash<std::uint64_t>()( 963 hpx::naming::detail::strip_internal_bits_from_gid(gid.get_msb()))); 964 return h1 ^ (h2 << 1); 965 } 966 }; 967 } 968 969 #include <hpx/config/warnings_suffix.hpp> 970 971 #endif /*HPX_RUNTIME_NAMING_NAME_HPP*/ 972