Commit 37122f93 authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

corrected problem with SFINAE deduction in provider class not working with icc

parent 80f018fc
...@@ -23,7 +23,9 @@ int main(int argc, char** argv) { ...@@ -23,7 +23,9 @@ int main(int argc, char** argv) {
std::cout << "(prod) Server answered " << ret << std::endl; std::cout << "(prod) Server answered " << ret << std::endl;
std::string name("Matthieu"); std::string name("Matthieu");
hello.on(ph)(name); hello.on(ph)(name);
std::cout << "Done sending hello RPC, no response expected" << std::endl;
print.on(ph)(name); print.on(ph)(name);
std::cout << "Done sending print RPC, no response expected" << std::endl;
return 0; return 0;
} }
......
...@@ -78,30 +78,36 @@ public: ...@@ -78,30 +78,36 @@ public:
m_engine.finalize(); m_engine.finalize();
} }
/**
* @brief Defines an RPC using a member function of the child class. private:
* The member function should have a const request& as first parameter
* and use this request parameter to respond to the client. // define_member as RPC for the case return value is NOT void and
* // the first argument is a request. The return value should be ignored,
* @tparam S type of the name (e.g. C-like string or std::string) // since the user is expected to call req.respond(...).
* @tparam R return value of the member function template<typename S, typename R, typename A1, typename ... Args>
* @tparam Args Arguments of the member function remote_procedure define_member(
* @param name name of the RPC S&& name,
* @param T::*func member function R(T::*func)(A1, Args...),
*/ const std::integral_constant<bool, false>& r_is_void,
template<typename S, typename R, typename ... Args> const std::integral_constant<bool, true>& first_arg_is_request,
remote_procedure define(S&& name, R(T::*func)(const request&, Args...), const pool& p = pool()) { const pool& p) {
T* self = dynamic_cast<T*>(this); T* self = dynamic_cast<T*>(this);
std::function<void(const request&, Args...)> fun = [self, func](const request& r, Args... args) { std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) {
(self->*func)(r, args...); (self->*func)(req, args...);
}; };
return m_engine.define(std::forward<S>(name), fun, m_provider_id, p); return m_engine.define(std::forward<S>(name), fun, m_provider_id, p);
} }
private: // define_member as RPC for the case the return value is NOT void
// and the request is not passed to the function. The return value
// should be sent using req.respond(...).
template<typename S, typename R, typename ... Args> template<typename S, typename R, typename ... Args>
remote_procedure define_member(S&& name, R(T::*func)(Args...), const std::integral_constant<bool, false>&, const pool& p = pool()) { remote_procedure define_member(
S&& name,
R(T::*func)(Args...),
const std::integral_constant<bool, false>& r_is_void,
const std::integral_constant<bool, false>& first_arg_is_request,
const pool& p) {
T* self = dynamic_cast<T*>(this); T* self = dynamic_cast<T*>(this);
std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) { std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) {
R r = (self->*func)(args...); R r = (self->*func)(args...);
...@@ -110,8 +116,32 @@ private: ...@@ -110,8 +116,32 @@ private:
return m_engine.define(std::forward<S>(name), fun, m_provider_id, p); return m_engine.define(std::forward<S>(name), fun, m_provider_id, p);
} }
// define_memver as RPC for the case the return value IS void
// and the first argument is a request. The user is expected to call
// req.respond(...) himself.
template<typename S, typename R, typename A1, typename ... Args>
remote_procedure define_member(
S&& name,
R(T::*func)(A1, Args...),
const std::integral_constant<bool, true>& r_is_void,
const std::integral_constant<bool, true>& first_arg_is_request,
const pool& p = pool()) {
T* self = dynamic_cast<T*>(this);
std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) {
(self->*func)(req, args...);
};
return m_engine.define(std::forward<S>(name), fun, m_provider_id, p);
}
// define_member as RPC for the case the return value IS void
// and the first argument IS NOT a request. We call disable_response.
template<typename S, typename R, typename ... Args> template<typename S, typename R, typename ... Args>
remote_procedure define_member(S&& name, R(T::*func)(Args...), const std::integral_constant<bool, true>&, const pool& p = pool()) { remote_procedure define_member(
S&& name,
R(T::*func)(Args...),
const std::integral_constant<bool, true>& r_is_void,
const std::integral_constant<bool, false>& first_arg_is_request,
const pool& p = pool()) {
T* self = dynamic_cast<T*>(this); T* self = dynamic_cast<T*>(this);
std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) { std::function<void(const request&, Args...)> fun = [self, func](const request& req, Args... args) {
(self->*func)(args...); (self->*func)(args...);
...@@ -122,33 +152,42 @@ private: ...@@ -122,33 +152,42 @@ private:
protected: protected:
/** /**
* @brief Defines an RPC from a member function of the child class. * @brief Defines an RPC using a member function of the child class.
* This member function doesn't have a const request& paramater, so
* the RPC will be formed by assuming the return value of the function
* is what is sent back to the client (nothing is sent back if the
* return type is void). If the member function returns something but
* this return value should not be sent back to the client, the caller
* can pass ignore_return_value() as last argument of define().
* *
* @tparam S Type of the RPC name (e.g. std::string) * @tparam S type of the name (e.g. C-like string or std::string)
* @tparam R Return value of the member function. * @tparam R return value of the member function
* @tparam Args Argument types of the member function. * @tparam A1 type of the first argument of the member function
* @tparam X Dispatcher type. * @tparam Args type of other arguments of the member function
* @param name Name of the RPC. * @tparam FIRST_ARG_IS_REQUEST automatically deducing whether the first type is a thallium::request
* @param T::*func Member function. * @tparam R_IS_VOID automatically deducing whether the return value is void
* @param p Argobots pool to use to execute the RPC. * @param name name of the RPC
* @param T::*func member function
* @param p Argobots pool
*/ */
template<typename S, typename R, typename ... Args, typename X = typename std::is_void<R>::type> template<typename S, typename R, typename A1, typename ... Args,
inline remote_procedure define(S&& name, R(T::*func)(Args...), const pool& p = pool(), X x = X()) { typename FIRST_ARG_IS_REQUEST = typename std::is_same<A1, const request&>::type,
return define_member(std::forward<S>(name), func, x, p); typename R_IS_VOID = typename std::is_void<R>::type>
inline remote_procedure define(S&& name, R(T::*func)(A1, Args...), const pool& p, R_IS_VOID r_is_void = R_IS_VOID()) {
return define_member(std::forward<S>(name), func, r_is_void, FIRST_ARG_IS_REQUEST(), p);
} }
/** template<typename S, typename R, typename A1, typename ... Args,
* @brief Same as the previous function but does not take a pool. typename FIRST_ARG_IS_REQUEST = typename std::is_same<A1, const request&>::type,
*/ typename R_IS_VOID = typename std::is_void<R>::type>
template<typename S, typename R, typename ... Args, typename X = typename std::is_void<R>::type> inline remote_procedure define(S&& name, R(T::*func)(A1, Args...), R_IS_VOID r_is_void = R_IS_VOID()) {
inline remote_procedure define(S&& name, R(T::*func)(Args...), X x) { return define_member(std::forward<S>(name), func, r_is_void, FIRST_ARG_IS_REQUEST(), pool());
return define_member(std::forward<S>(name), func, x, pool()); }
template<typename S, typename R, typename R_IS_VOID = typename std::is_void<R>::type>
inline remote_procedure define(S&& name, R(T::*func)(), const pool& p, R_IS_VOID r_is_void = R_IS_VOID()) {
std::integral_constant<bool, false> first_arg_is_request;
return define_member(std::forward<S>(name), func, r_is_void, first_arg_is_request, p);
}
template<typename S, typename R, typename R_IS_VOID = typename std::is_void<R>::type>
inline remote_procedure define(S&& name, R(T::*func)(), R_IS_VOID r_is_void = R_IS_VOID()) {
std::integral_constant<bool, false> first_arg_is_request;
return define_member(std::forward<S>(name), func, r_is_void, first_arg_is_request, pool());
} }
public: public:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment