/////////////////////////////////////////////////////////////////////////// // the code below is needed to bootstrap the parcel layer void parcelport::early_pending_parcel_handler( boost::system::error_code const& ec, parcel const & p) { if (ec) { // all errors during early parcel handling are fatal std::exception_ptr exception = HPX_GET_EXCEPTION(ec, "early_pending_parcel_handler", "error while handling early parcel: " + ec.message() + "(" + std::to_string(ec.value()) + ")" + parcelset::dump_parcel(p)); hpx::report_error(exception); return; } #if defined(HPX_HAVE_APEX) && defined(HPX_HAVE_PARCEL_PROFILING) // tell APEX about the sent parcel apex::send(p.parcel_id().get_lsb(), p.size(), p.destination_locality_id()); #endif }
void parcelhandler::put_parcel(parcel p, write_handler_type f) { HPX_ASSERT(resolver_); naming::id_type const* ids = p.destinations(); naming::address* addrs = p.addrs(); // During bootstrap this is handled separately (see // addressing_service::resolve_locality. if (0 == hpx::threads::get_self_ptr() && !hpx::is_starting()) { HPX_ASSERT(resolver_); naming::gid_type locality = naming::get_locality_from_gid(ids[0].get_gid()); if (!resolver_->has_resolved_locality(locality)) { // reschedule request as an HPX thread to avoid hangs void (parcelhandler::*put_parcel_ptr) ( parcel p, write_handler_type f ) = &parcelhandler::put_parcel; threads::register_thread_nullary( util::bind( util::one_shot(put_parcel_ptr), this, std::move(p), std::move(f)), "parcelhandler::put_parcel", threads::pending, true, threads::thread_priority_boost); return; } } // properly initialize parcel init_parcel(p); bool resolved_locally = true; #if !defined(HPX_SUPPORT_MULTIPLE_PARCEL_DESTINATIONS) if (!addrs[0]) { resolved_locally = resolver_->resolve_local(ids[0], addrs[0]); } #else std::size_t size = p.size(); if (0 == size) { HPX_THROW_EXCEPTION(network_error, "parcelhandler::put_parcel", "no destination address given"); return; } if (1 == size) { if (!addrs[0]) resolved_locally = resolver_->resolve_local(ids[0], addrs[0]); } else { boost::dynamic_bitset<> locals; resolved_locally = resolver_->resolve_local(ids, addrs, size, locals); } #endif if (!p.parcel_id()) p.parcel_id() = parcel::generate_unique_id(); using util::placeholders::_1; using util::placeholders::_2; write_handler_type wrapped_f = util::bind(&detail::parcel_sent_handler, std::move(f), _1, _2); // If we were able to resolve the address(es) locally we send the // parcel directly to the destination. if (resolved_locally) { // dispatch to the message handler which is associated with the // encapsulated action typedef std::pair<boost::shared_ptr<parcelport>, locality> destination_pair; destination_pair dest = find_appropriate_destination(addrs[0].locality_); if (load_message_handlers_) { policies::message_handler* mh = p.get_message_handler(this, dest.second); if (mh) { mh->put_parcel(dest.second, std::move(p), std::move(wrapped_f)); return; } } dest.first->put_parcel(dest.second, std::move(p), std::move(wrapped_f)); return; } // At least one of the addresses is locally unknown, route the parcel // to the AGAS managing the destination. ++count_routed_; resolver_->route(std::move(p), std::move(wrapped_f)); }