/////////////////////////////////////////////////////////////////////////// // Call-back function for parcelHandler to call when new parcels are received void action_manager::fetch_parcel( parcelset::parcelhandler& parcel_handler, naming::gid_type const& parcel_id) { parcelset::parcel p; if (!parcel_handler.get_parcel(p, parcel_id)) return; while (threads::threadmanager_is(starting)) { boost::this_thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(HPX_NETWORK_RETRIES_SLEEP)); } // Give up if we're shutting down. if (threads::threadmanager_is(stopping)) { LPT_(debug) << "action_manager: fetch_parcel: dropping late " "parcel " << p; return; } // write this parcel to the log LPT_(debug) << "action_manager: fetch_parcel: " << p; appl_.schedule_action(p); }
// The original parcel-sent handler is wrapped to keep the parcel alive // until after the data has been reliably sent (which is needed for zero // copy serialization). void parcel_sent_handler(parcelset::parcelhandler& ph, boost::system::error_code const& ec, parcelset::parcel const& p) { // invoke the original handler ph.invoke_write_handler(ec, p); // inform termination detection of a sent message if (!p.does_termination_detection()) hpx::detail::dijkstra_make_black(); }
/////////////////////////////////////////////////////////////////////////// // Call-back function for parcelHandler to call when new parcels are received void action_manager::fetch_parcel( parcelset::parcelhandler& parcel_handler, naming::gid_type const& parcel_id) { parcelset::parcel p; if (!parcel_handler.get_parcel(p, parcel_id)) return; while (threads::threadmanager_is(starting)) { boost::this_thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(HPX_NETWORK_RETRIES_SLEEP)); } // Give up if we're shutting down. if (threads::threadmanager_is(stopping)) { LPT_(debug) << "action_manager: fetch_parcel: dropping late " "parcel " << p; return; } // write this parcel to the log LPT_(debug) << "action_manager: fetch_parcel: " << p; // decode the action-type in the parcel continuation_type cont = p.get_continuation(); actions::action_type act = p.get_action(); actions::base_action::action_type acttype = act->get_action_type(); int comptype = act->get_component_type(); naming::locality dest = p.get_destination_locality(); // fetch the set of destinations std::vector<naming::address> const& addrs = p.get_destination_addrs(); // if the parcel carries a continuation it should be directed to a // single destination BOOST_ASSERT(!cont || addrs.size() == 1); // schedule a thread for each of the destinations threads::threadmanager_base& tm = appl_.get_thread_manager(); std::vector<naming::address>::const_iterator end = addrs.end(); for (std::vector<naming::address>::const_iterator it = addrs.begin(); it != end; ++it) { naming::address const& addr = *it; // make sure this parcel destination matches the proper locality BOOST_ASSERT(dest == addr.locality_); // decode the local virtual address of the parcel naming::address::address_type lva = addr.address_; // by convention, a zero address references the local runtime // support component if (0 == lva) lva = appl_.get_runtime_support_raw_gid().get_lsb(); // make sure the component_type of the action matches the // component type in the destination address if (HPX_UNLIKELY(!components::types_are_compatible( addr.type_, comptype))) { hpx::util::osstream strm; strm << " types are not compatible: destination_type(" << addr.type_ << ") action_type(" << comptype << ") parcel (" << p << ")"; HPX_THROW_EXCEPTION(bad_component_type, "action_manager::fetch_parcel", hpx::util::osstream_get_string(strm)); } // either directly execute the action or create a new thread if (actions::base_action::direct_action == acttype) { // direct execution of the action if (!cont) { // No continuation is to be executed. act->get_thread_function(lva)(threads::wait_signaled); } else { // This parcel carries a continuation, we execute a wrapper // handling all related functionality. act->get_thread_function(cont, lva)(threads::wait_signaled); } } else { // dispatch action, register work item either with or without // continuation support if (!cont) { // No continuation is to be executed, register the plain // action and the local-virtual address with the TM only. threads::thread_init_data data; tm.register_work( act->get_thread_init_data(lva, data), threads::pending); } else { // This parcel carries a continuation, register a wrapper // which first executes the original thread function as // required by the action and triggers the continuations // afterwards. threads::thread_init_data data; tm.register_work( act->get_thread_init_data(cont, lva, data), threads::pending); } } } }