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

Automatically synthesize message types for sends to arbitrary handlers #276

Closed
PhilMiller opened this issue Feb 19, 2019 · 14 comments · Fixed by #2064 or #2136 · May be fixed by #2085
Closed

Automatically synthesize message types for sends to arbitrary handlers #276

PhilMiller opened this issue Feb 19, 2019 · 14 comments · Fixed by #2064 or #2136 · May be fixed by #2085
Assignees
Labels
c++17 Things to be done once we can rely on C++17 support

Comments

@PhilMiller
Copy link
Member

Following on #272, I think it would not be all that difficult to write template code that would let applications make a send call with arguments matching those of some handler, and the template code would take care of describing a suitable message type and actual target handler to unwrap the message and make the call.

The pieces I see playing into this are roughly as follows:

  • A method (probably easy enough to write with std::forward_as_tuple
    template <void (*Func)(Args...), typename Args...> sendMagic(Args&& ...args)
  • A very generic message type
    template <typename Args...> struct MagicMsg { std::tuple<...Args> a;};
  • A very generic handler function to call the actual handler via std::apply
    template <void (*Func)(Args...), typename Args...> receiveMagic(MagicMsg<...Args>* m)

Once the simplest cases are working, we should probably apply a type trait to each of the argument types to represent how they should be represented in the message / on the wire, in cases where they shouldn't be literal. In particular, automatic handling of anything array-like on the sending side coming out to whatever array-like thing the receiver expects would be very convenient.

@PhilMiller
Copy link
Member Author

@mperrinel will start on this - assigned the rest of us as observers.

@hobywan
Copy link
Contributor

hobywan commented Feb 19, 2019

Hello.
I can handle that.
Thanks

@PhilMiller
Copy link
Member Author

Turns out Jonathan largely implemented this in src/vt/parameterization. It probably can use work to bring up to date and better integrate with how VT is being used.

@lifflander
Copy link
Collaborator

@hobywan Please comment with your plan for integrating this more broadly in VT. Let's have a discussion on that before you get started

@lifflander
Copy link
Collaborator

lifflander commented Feb 27, 2019

To document what I encountered before: the fundamental problem with this is that you can't infer the arguments for a value-template (in the standard called a "non-type template"):

struct MyCol : Collection<MyCol,Index1D> {
  void method(int a, int b);
};

template <typename ColT, typename... Args>
using ActiveColMemberArgsFnType = void(ColT::*)(Args...);

template <typename... Args, ActiveColMemberArgsFnType<ColT,Args...> f>
void send(Args&&... args) const;

proxy(i).send<&MyCol::method>(10,20);

@hobywan I'm not sure how to solve this, but this is the main problem to address for the API to be usable.

From reading the standard this is not possible in C++14: inferring the type of a non-type template. See this answer:

https://stackoverflow.com/questions/27372492/c-template-parameter-type-inference

This deficiency was addressed by the standard in C++17 with auto templates. P0127

@hobywan
Copy link
Contributor

hobywan commented Mar 5, 2019

I searched for workarounds without the use an auto template parameter, but I get stuck.
Since multiple templatized variants of sendData already exist in parameterization, I thought on ways to wrap them using only the handler as a template parameter.
It seems that it is not possible without using a macro such as:

#define send(handler) sendData<decltype(handler), &handler> 

like the example here.
An alternative would be to restrict the interface to unique handlers per message type (but may be overloaded to support compile-time polymorphism), and then apply a type trait to ensure that the correct handler is invoked for derived message or virtual collection types (not that of its parent).
In a nutshell, it redefines the message or virtual collection type to behave like a functor.
For the above example, the call would just be: proxy(i).send<MyCol>(10,20); with:

template <typename ColT, typename... Args>
EventType send(...) {
  // argument checking or parsing here
  auto const& handler = auto_registry::makeAutoHandler<ColT>(); // should be updated
  return sendData<ColT, handler>(std::forward<Tuple>(Args));
}

Another workaround would be to restrict this feature to be enabled only if C++17 is enabled (using macros) but that is far from being an elegant solution.

@PhilMiller
Copy link
Member Author

For reference, that template <auto v> feature is adopted in C++17 as P0127R2. GCC 7 and Clang 4 implement it, and Intel 19.0.1 claims to

@lifflander
Copy link
Collaborator

Making this low priority to implement as a opt-in when using C++17

@PhilMiller
Copy link
Member Author

Per http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0127r2.html#FeatureTestMacro, we can conditionalize relevant functionality and tests on __cpp_template_auto

@PhilMiller
Copy link
Member Author

More than a year later, Nvidia is still the laggard in implementing P0127 support. I'm going to de-assign this, just to take it off the radar.

@lifflander
Copy link
Collaborator

@PhilMiller Sounds like a plan. Should be have a label for back burner type tasks? Is pri:low enough to signify that?

@PhilMiller
Copy link
Member Author

Yeah, I think so.

@PhilMiller
Copy link
Member Author

And, as a note, Nvidia's compiler generally says that it doesn't implement partial standards, so we won't have any C++17 support from them until they offer complete C++17 support. We should maybe see if this code would work there in spite of their lacking support, possibly by it not parsing code that it's not going to need to generate anything for itself.

@PhilMiller
Copy link
Member Author

As of nvcc 11.0, C++17 support is available.

lifflander added a commit that referenced this issue Jun 13, 2023
lifflander added a commit that referenced this issue Jun 13, 2023
lifflander added a commit that referenced this issue Jun 13, 2023
lifflander added a commit that referenced this issue Jun 13, 2023
lifflander added a commit that referenced this issue Jun 13, 2023
lifflander added a commit that referenced this issue Jun 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++17 Things to be done once we can rely on C++17 support
Projects
None yet
5 participants