diff --git a/examples/collection/transpose.cc b/examples/collection/transpose.cc index 71a89272f7..dd813c926d 100644 --- a/examples/collection/transpose.cc +++ b/examples/collection/transpose.cc @@ -176,7 +176,7 @@ struct Block : vt::Collection { if (getIndex().x() == 0) { auto proxy = this->getCollectionProxy(); auto proxy_msg = vt::makeMessage(proxy.getProxy()); - vt::theMsg()->broadcastMsg(proxy_msg); + vt::theMsg()->broadcastMsg(proxy_msg); } } diff --git a/examples/hello_world/hello_world_functor.cc b/examples/hello_world/hello_world_functor.cc index 0b4dacdbb9..c579cf63d5 100644 --- a/examples/hello_world/hello_world_functor.cc +++ b/examples/hello_world/hello_world_functor.cc @@ -52,9 +52,21 @@ struct HelloMsg : vt::Message { { } }; +struct AnotherMsg : vt::Message{}; + struct HelloWorld { void operator()(HelloMsg* msg) const { - fmt::print("{}: Hello from node {}\n", vt::theContext()->getNode(), msg->from); + fmt::print("{}: HelloWorld -> Hello from node {}\n", vt::theContext()->getNode(), msg->from); + } +}; + +struct MultipleFunctions { + void operator()(HelloMsg* msg) const { + fmt::print("{}: MultipleFunctions -> Hello from node {}\n", vt::theContext()->getNode(), msg->from); + } + + void operator()(AnotherMsg* msg) const { + fmt::print("{}: MultipleFunctions with AnotherMsg\n", vt::theContext()->getNode()); } }; @@ -70,7 +82,21 @@ int main(int argc, char** argv) { if (this_node == 0) { auto msg = vt::makeMessage(this_node); - vt::theMsg()->broadcastMsg(msg); + + // 'HelloWorld' functor has only single 'operator()' declared + // so we can call send/broadcast without specifying message type + vt::theMsg()->broadcastMsg(msg); + + msg = vt::makeMessage(this_node); + vt::theMsg()->sendMsg(1, msg); + + // 'MultipleFunctions' functor declares more than one 'operator()' + // so we have to specify the type of the message, as it can't be deduced + auto new_msg = vt::makeMessage(); + vt::theMsg()->broadcastMsg(new_msg); + + msg = vt::makeMessage(this_node); + vt::theMsg()->sendMsg(1, msg); } vt::finalize(); diff --git a/src/vt/messaging/active.h b/src/vt/messaging/active.h index 9ef00cde2a..81271632d6 100644 --- a/src/vt/messaging/active.h +++ b/src/vt/messaging/active.h @@ -901,7 +901,7 @@ struct ActiveMessenger : runtime::component::PollableComponent */ template < typename FunctorT, - typename MsgT = typename util::FunctorExtractor::MessageType + typename MsgT > PendingSendType broadcastMsg( MsgPtrThief msg, @@ -909,6 +909,24 @@ struct ActiveMessenger : runtime::component::PollableComponent TagType tag = no_tag ); + /** + * \brief Broadcast a message. + * + * \note Takes ownership of the supplied message. + * + * \param[in] msg the message to broadcast + * \param[in] deliver_to_sender whether msg should be delivered to sender + * \param[in] tag the optional tag to put on the message + * + * \return the \c PendingSend for the broadcast + */ + template + PendingSendType broadcastMsg( + MsgPtrThief::MessageType> msg, + bool deliver_to_sender = true, + TagType tag = no_tag + ); + /** * \brief Broadcast a message. * @@ -941,16 +959,31 @@ struct ActiveMessenger : runtime::component::PollableComponent * * \return the \c PendingSend for the send */ - template < - typename FunctorT, - typename MsgT = typename util::FunctorExtractor::MessageType - > + template PendingSendType sendMsg( NodeType dest, MsgPtrThief msg, TagType tag = no_tag ); + /** + * \brief Send a message with a type-safe handler. + * + * \note Takes ownership of the supplied message. + * + * \param[in] dest the destination node to send the message to + * \param[in] msg the message to broadcast + * \param[in] tag the tag to put on the message + * + * \return the \c PendingSend for the send + */ + template + PendingSendType sendMsg( + NodeType dest, + MsgPtrThief::MessageType> msg, + TagType tag = no_tag + ); + /** * \brief Send a message. * diff --git a/src/vt/messaging/active.impl.h b/src/vt/messaging/active.impl.h index 4207e0eb63..d4c8da8a78 100644 --- a/src/vt/messaging/active.impl.h +++ b/src/vt/messaging/active.impl.h @@ -359,6 +359,16 @@ ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsg( ); } +template +ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsg( + MsgPtrThief::MessageType> msg, + bool deliver_to_sender, + TagType tag +) { + using MsgT = typename util::FunctorExtractor::MessageType; + return broadcastMsg(msg, deliver_to_sender, tag); +} + template ActiveMessenger::PendingSendType ActiveMessenger::sendMsg( NodeType dest, @@ -370,6 +380,16 @@ ActiveMessenger::PendingSendType ActiveMessenger::sendMsg( return sendMsgImpl(dest, han, msgptr, msgsize_not_specified, tag); } +template +ActiveMessenger::PendingSendType ActiveMessenger::sendMsg( + NodeType dest, + MsgPtrThief::MessageType> msg, + TagType tag +) { + using MsgT = typename util::FunctorExtractor::MessageType; + return sendMsg(dest, msg, tag); +} + template ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsgAuto( MsgPtrThief msg, diff --git a/src/vt/utils/static_checks/functor.h b/src/vt/utils/static_checks/functor.h index 1d125243bd..1342d5b088 100644 --- a/src/vt/utils/static_checks/functor.h +++ b/src/vt/utils/static_checks/functor.h @@ -59,6 +59,13 @@ struct FunctorTraits { using ReturnType = ReturnT; }; +template +struct FunctorTraits { + using FunctorType = FunctorT; + using MessageType = MsgT; + using ReturnType = ReturnT; +}; + template < typename FunctorT, typename FunctorFnT = decltype(&FunctorT::operator()), diff --git a/tutorial/tutorial_1b.h b/tutorial/tutorial_1b.h index b84ec57458..0596b4f8c3 100644 --- a/tutorial/tutorial_1b.h +++ b/tutorial/tutorial_1b.h @@ -154,7 +154,7 @@ static void msgHandlerA(MyMsg* msg) { NodeType const to_node = 0; auto msg2 = ::vt::makeMessage(10,20); - ::vt::theMsg()->sendMsg(to_node, msg2); + ::vt::theMsg()->sendMsg(to_node, msg2); // Alternate/equivalent form with explicit (and optional) std::move: //