Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1260: Fix active messaging functor inference using the FunctorExtractor #1330

Merged
merged 9 commits into from
May 7, 2021
2 changes: 1 addition & 1 deletion examples/collection/transpose.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ struct Block : vt::Collection<Block, vt::Index1D> {
if (getIndex().x() == 0) {
auto proxy = this->getCollectionProxy();
auto proxy_msg = vt::makeMessage<ProxyMsg>(proxy.getProxy());
vt::theMsg()->broadcastMsg<SetupGroup,ProxyMsg>(proxy_msg);
vt::theMsg()->broadcastMsg<SetupGroup>(proxy_msg);
}
}

Expand Down
30 changes: 28 additions & 2 deletions examples/hello_world/hello_world_functor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
};

Expand All @@ -70,7 +82,21 @@ int main(int argc, char** argv) {

if (this_node == 0) {
auto msg = vt::makeMessage<HelloMsg>(this_node);
vt::theMsg()->broadcastMsg<HelloWorld,HelloMsg>(msg);

// 'HelloWorld' functor has only single 'operator()' declared
// so we can call send/braodcast without specyfing message type
vt::theMsg()->broadcastMsg<HelloWorld>(msg);

msg = vt::makeMessage<HelloMsg>(this_node);
vt::theMsg()->sendMsg<HelloWorld>(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<AnotherMsg>();
vt::theMsg()->broadcastMsg<MultipleFunctions, AnotherMsg>(new_msg);

new_msg = vt::makeMessage<AnotherMsg>();
vt::theMsg()->sendMsg<MultipleFunctions, AnotherMsg>(1, new_msg);
}

vt::finalize();
Expand Down
43 changes: 38 additions & 5 deletions src/vt/messaging/active.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,14 +901,32 @@ struct ActiveMessenger : runtime::component::PollableComponent<ActiveMessenger>
*/
template <
typename FunctorT,
typename MsgT = typename util::FunctorExtractor<FunctorT>::MessageType
typename MsgT
>
PendingSendType broadcastMsg(
MsgPtrThief<MsgT> msg,
bool deliver_to_sender = true,
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 <typename FunctorT>
PendingSendType broadcastMsg(
MsgPtrThief<typename util::FunctorExtractor<FunctorT>::MessageType> msg,
bool deliver_to_sender = true,
TagType tag = no_tag
);

/**
* \brief Broadcast a message.
*
Expand Down Expand Up @@ -941,16 +959,31 @@ struct ActiveMessenger : runtime::component::PollableComponent<ActiveMessenger>
*
* \return the \c PendingSend for the send
*/
template <
typename FunctorT,
typename MsgT = typename util::FunctorExtractor<FunctorT>::MessageType
>
template <typename FunctorT,typename MsgT>
PendingSendType sendMsg(
NodeType dest,
MsgPtrThief<MsgT> 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 <typename FunctorT>
PendingSendType sendMsg(
NodeType dest,
MsgPtrThief<typename util::FunctorExtractor<FunctorT>::MessageType> msg,
TagType tag = no_tag
);

/**
* \brief Send a message.
*
Expand Down
20 changes: 20 additions & 0 deletions src/vt/messaging/active.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@ ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsg(
);
}

template <typename FunctorT>
ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsg(
MsgPtrThief<typename util::FunctorExtractor<FunctorT>::MessageType> msg,
bool deliver_to_sender,
TagType tag
) {
using MsgT = typename util::FunctorExtractor<FunctorT>::MessageType;
return broadcastMsg<FunctorT, MsgT>(msg, deliver_to_sender, tag);
}

template <typename FunctorT, typename MsgT>
ActiveMessenger::PendingSendType ActiveMessenger::sendMsg(
NodeType dest,
Expand All @@ -370,6 +380,16 @@ ActiveMessenger::PendingSendType ActiveMessenger::sendMsg(
return sendMsgImpl<MsgT>(dest, han, msgptr, msgsize_not_specified, tag);
}

template <typename FunctorT>
ActiveMessenger::PendingSendType ActiveMessenger::sendMsg(
NodeType dest,
MsgPtrThief<typename util::FunctorExtractor<FunctorT>::MessageType> msg,
TagType tag
) {
using MsgT = typename util::FunctorExtractor<FunctorT>::MessageType;
return sendMsg<FunctorT, MsgT>(dest, msg, tag);
}

template <typename FunctorT, typename MsgT>
ActiveMessenger::PendingSendType ActiveMessenger::broadcastMsgAuto(
MsgPtrThief<MsgT> msg,
Expand Down
8 changes: 8 additions & 0 deletions src/vt/utils/static_checks/functor.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

#include "vt/config.h"


namespace vt { namespace util {

template <typename FunctorT>
Expand All @@ -59,6 +60,13 @@ struct FunctorTraits<ReturnT(FunctorT::*)(MsgT*)> {
using ReturnType = ReturnT;
};

template <typename FunctorT, typename ReturnT, typename MsgT>
struct FunctorTraits<ReturnT(FunctorT::*)(MsgT*) const> {
using FunctorType = FunctorT;
using MessageType = MsgT;
using ReturnType = ReturnT;
};

template <
typename FunctorT,
typename FunctorFnT = decltype(&FunctorT::operator()),
Expand Down
2 changes: 1 addition & 1 deletion tutorial/tutorial_1b.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ static void msgHandlerA(MyMsg* msg) {
NodeType const to_node = 0;
auto msg2 = ::vt::makeMessage<MyMsg>(10,20);

::vt::theMsg()->sendMsg<MsgHandlerB, MyMsg>(to_node, msg2);
::vt::theMsg()->sendMsg<MsgHandlerB>(to_node, msg2);

// Alternate/equivalent form with explicit (and optional) std::move:
//
Expand Down