future<id_type> trigger_migrate_component( id_type const& to_migrate, DistPolicy const& policy) { if (!traits::component_supports_migration<Component>::call()) { return hpx::make_exceptional_future<id_type>( HPX_GET_EXCEPTION(invalid_status, "hpx::components::server::trigger_migrate_component", "attempting to migrate an instance of a component which " "does not support migration")); } if (naming::get_locality_id_from_id(to_migrate) != get_locality_id()) { return hpx::make_exceptional_future<id_type>( HPX_GET_EXCEPTION(invalid_status, "hpx::components::server::trigger_migrate_component", "this function has to be executed on the locality " "responsible for managing the address of the given object")); } auto r = agas::begin_migration(to_migrate); // perform actual object migration typedef migrate_component_action<Component, DistPolicy> action_type; return async<action_type>(r.first, to_migrate, r.second, policy) .then( [to_migrate](future<id_type> && f) -> id_type { agas::end_migration(to_migrate); return f.get(); }); }
future<id_type> migrate_component( id_type const& to_migrate, naming::address const& addr, DistPolicy const& policy) { // 'migration' to same locality as before is a no-op if (policy.get_next_target() == hpx::find_here()) { return make_ready_future(to_migrate); } if (!traits::component_supports_migration<Component>::call()) { return hpx::make_exceptional_future<hpx::id_type>( HPX_GET_EXCEPTION(invalid_status, "hpx::components::server::migrate_component", "attempting to migrate an instance of a component which " "does not support migration")); } // retrieve pointer to object (must be local) std::shared_ptr<Component> ptr = hpx::detail::get_ptr_for_migration<Component>(addr, to_migrate); // perform actual migration by sending data over to target locality return detail::migrate_component_postproc<Component>( ptr, to_migrate, policy); }
hpx::future<void> mark_as_migrated(hpx::id_type const& to_migrate) { // we need to first lock the AGAS migrated objects table, only then // access (lock) the object return agas::mark_as_migrated(to_migrate.get_gid(), [this]() mutable -> std::pair<bool, hpx::future<void> > { std::unique_lock<mutex_type> l(mtx_); // make sure that no migration is currently in flight if (was_marked_for_migration_) { l.unlock(); return std::make_pair(false, hpx::make_exceptional_future<void>( HPX_GET_EXCEPTION(invalid_status, "migration_support::mark_as_migrated", "migration operation is already in flight") )); } if (1 == pin_count_) { // all is well, migration can be triggered now return std::make_pair(true, make_ready_future()); } // delay migrate operation until pin count goes to zero was_marked_for_migration_ = true; l.unlock(); return std::make_pair(true, trigger_migration_.get_future()); }); }
future<void> abort_pending() { typedef lcos::base_lco::set_exception_action action_type; HPX_ASSERT(this->get_gid()); boost::exception_ptr exception = HPX_GET_EXCEPTION(hpx::no_success, "queue::abort_pending", ""); return hpx::async<action_type>(this->get_gid(), exception); }
future<id_type> perform_migrate_component( id_type const& to_migrate, DistPolicy const& policy) { if (!traits::component_supports_migration<Component>::call()) { return hpx::make_exceptional_future<id_type>( HPX_GET_EXCEPTION(invalid_status, "hpx::components::server::perform_migrate_component", "attempting to migrate an instance of a component which " "does not support migration")); } // retrieve pointer to object (must be local) return hpx::get_ptr<Component>(to_migrate) .then( [=](future<std::shared_ptr<Component> > && f) -> future<id_type> { future<void> trigger_migration; { std::shared_ptr<Component> ptr = f.get(); // Delay the start of the migration operation until no // more actions (threads) are pending or currently // running for the given object (until the object is // unpinned). trigger_migration = ptr->mark_as_migrated(to_migrate); // Unpin the object, will trigger migration if this is // the only pin-count. } // Once the migration is possible (object is not pinned // anymore trigger the necessary actions) return trigger_migration .then( launch::async, // run on separate thread [=](future<void> && f) -> future<id_type> { f.get(); // rethrow exceptions // now trigger 2nd step of migration typedef trigger_migrate_component_action< Component, DistPolicy > action_type; return async<action_type>( naming::get_locality_from_id(to_migrate), to_migrate, policy); }); }); }
/////////////////////////////////////////////////////////////////////////////// // Forwarding of hpx_startup::user_main, if necessary. This has to be in a // separate translation unit to ensure the linker can pick or ignore this // function, depending on whether the main executable defines this symbol // or not. int hpx_startup::user_main(int argc, char** argv) { // If we have seen unknown command line options we can throw here as we // know that the user is not going to look at the arguments. std::string unknown_command_line = hpx::get_config_entry("hpx.unknown_cmd_line_option", ""); if (!unknown_command_line.empty()) { hpx::detail::report_exception_and_terminate( HPX_GET_EXCEPTION(hpx::bad_parameter, "hpx_startup::user_main", "unknown command line option(s): " + unknown_command_line) ); } return hpx_startup::user_main(); }
/////////////////////////////////////////////////////////////////////////// // 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 }