Ejemplo n.º 1
0
    ///////////////////////////////////////////////////////////////////////////
    // 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
    }
Ejemplo n.º 2
0
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));
}