diff --git a/hpx/lcos/async_continue_fwd.hpp b/hpx/lcos/async_continue_fwd.hpp index 8b0d7791eb04..e1affdc7b4ab 100644 --- a/hpx/lcos/async_continue_fwd.hpp +++ b/hpx/lcos/async_continue_fwd.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -26,7 +26,7 @@ namespace hpx { template struct result_of_async_continue - : actions::detail::remote_action_result< + : traits::action_remote_result< typename util::result_of::type( naming::id_type, typename hpx::traits::extract_action< diff --git a/hpx/runtime/actions/action_invoke_no_more_than.hpp b/hpx/runtime/actions/action_invoke_no_more_than.hpp index 133e4078f8f0..17d134f809b3 100644 --- a/hpx/runtime/actions/action_invoke_no_more_than.hpp +++ b/hpx/runtime/actions/action_invoke_no_more_than.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -170,8 +171,11 @@ namespace hpx { namespace actions { namespace detail void trigger_value(remote_result_type && result) { if(cont_) + { + HPX_ASSERT(0 != dynamic_cast(cont_.get())); static_cast(cont_.get())-> trigger_value(std::move(result)); + } construct_semaphore_type::get_sem().signal(); } diff --git a/hpx/runtime/actions/action_support.hpp b/hpx/runtime/actions/action_support.hpp index dfd1fd676fdc..33becc15315e 100644 --- a/hpx/runtime/actions/action_support.hpp +++ b/hpx/runtime/actions/action_support.hpp @@ -14,13 +14,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include @@ -80,6 +80,41 @@ namespace hpx { namespace traits hpx::actions::detail::action_serialization_data> : boost::mpl::true_ {}; + + namespace detail + { + /////////////////////////////////////////////////////////////////////// + // If an action returns a future, we need to do special things + template <> + struct action_remote_result_customization_point + { + typedef util::unused_type type; + }; + + template + struct action_remote_result_customization_point > + { + typedef Result type; + }; + + template <> + struct action_remote_result_customization_point > + { + typedef hpx::util::unused_type type; + }; + + template + struct action_remote_result_customization_point > + { + typedef Result type; + }; + + template <> + struct action_remote_result_customization_point > + { + typedef hpx::util::unused_type type; + }; + } }} /// \endcond @@ -111,38 +146,6 @@ namespace hpx { namespace actions return util::type_id::typeid_.type_id(); } #endif - - /////////////////////////////////////////////////////////////////////// - // If an action returns a future, we need to do special things - template <> - struct remote_action_result - { - typedef util::unused_type type; - }; - - template - struct remote_action_result > - { - typedef Result type; - }; - - template <> - struct remote_action_result > - { - typedef hpx::util::unused_type type; - }; - - template - struct remote_action_result > - { - typedef Result type; - }; - - template <> - struct remote_action_result > - { - typedef hpx::util::unused_type type; - }; } /////////////////////////////////////////////////////////////////////////// diff --git a/hpx/runtime/actions/basic_action.hpp b/hpx/runtime/actions/basic_action.hpp index 2f18885d0678..35a86530d04e 100644 --- a/hpx/runtime/actions/basic_action.hpp +++ b/hpx/runtime/actions/basic_action.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -131,14 +132,12 @@ namespace hpx { namespace actions typedef Derived derived_type; // result_type represents the type returned when invoking operator() - typedef - typename traits::promise_local_result< - R - >::type - result_type; + typedef typename traits::promise_local_result::type result_type; + // The remote_result_type is the remote type for the type_continuation - typedef typename detail::remote_action_result::type remote_result_type; - // The remote_result_type is the local type for the type_continuation + typedef typename traits::action_remote_result::type remote_result_type; + + // The local_result_type is the local type for the type_continuation typedef typename traits::promise_local_result< remote_result_type diff --git a/hpx/runtime/actions/continuation.hpp b/hpx/runtime/actions/continuation.hpp index 46679643fd72..020f1675e156 100644 --- a/hpx/runtime/actions/continuation.hpp +++ b/hpx/runtime/actions/continuation.hpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -332,8 +332,16 @@ namespace hpx { namespace actions { try { HPX_ASSERT(result.is_ready()); - static_cast*>(cont.get())-> - trigger(result.get()); + HPX_ASSERT((0 != + dynamic_cast< + typed_continuation* + >(cont.get()))); + + static_cast< + typed_continuation* + >(cont.get())->trigger( + hpx::util::detail::decay_copy(result.get()) + ); } catch (...) { // make sure hpx::exceptions are propagated back to the client @@ -359,17 +367,14 @@ namespace hpx { namespace actions void trigger_impl_future(boost::mpl::true_, std::unique_ptr cont, F&& f, Ts&&... vs) { + typedef typename traits::future_traits::type type; typedef - typename traits::future_traits< - Future - >::type type; - typedef - typename detail::remote_action_result::type + typename traits::action_remote_result::type remote_result_type; typedef typename std::is_void::type is_void; Future result = util::invoke(std::forward(f), - std::forward(vs)...); + std::forward(vs)...); if(result.is_ready()) { @@ -396,9 +401,15 @@ namespace hpx { namespace actions std::unique_ptr cont, F&& f, Ts&&... vs) { try { - static_cast*>(cont.get())-> - trigger(util::invoke(std::forward(f), - std::forward(vs)...)); + HPX_ASSERT((0 != + dynamic_cast< + typed_continuation* + >(cont.get()))); + + static_cast< + typed_continuation* + >(cont.get())->trigger( + util::invoke(std::forward(f), std::forward(vs)...)); } catch (...) { // make sure hpx::exceptions are propagated back to the client @@ -422,12 +433,12 @@ namespace hpx { namespace actions template void trigger(std::unique_ptr cont, F&& f, Ts&&... vs) { - typedef typename util::result_of::type - result_type; + typedef typename util::result_of::type result_type; typedef typename std::is_same::type is_void; + detail::trigger_impl(is_void(), std::move(cont), std::forward(f), std::forward(vs)...); } @@ -896,6 +907,11 @@ namespace hpx { namespace actions this->trigger(); } + virtual void trigger_value(util::unused_type const&) + { + this->trigger(); + } + private: char const* get_continuation_name() const { @@ -925,10 +941,19 @@ namespace hpx { namespace actions template void continuation::trigger(Arg0 && arg0) { + // The dynamic cast decays the argument type to avoid the assert firing + // for cases when Arg0 is a const&. This does not make the code invalid + // as trigger_value (which is a virtual function) takes its argument + // by && anyways. + HPX_ASSERT(0 != dynamic_cast< + typed_continuation::type> * + >(this)); + // The static_cast is safe as we know that Arg0 is the result type // of the executed action (see apply.hpp). - static_cast *>(this)->trigger_value( - std::forward(arg0)); + static_cast< + typed_continuation::type> * + >(this)->trigger_value(std::forward(arg0)); } }} diff --git a/hpx/runtime/actions/detail/remote_action_result.hpp b/hpx/runtime/actions/detail/remote_action_result.hpp deleted file mode 100644 index e4e63ba88e8b..000000000000 --- a/hpx/runtime/actions/detail/remote_action_result.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2007-2014 Hartmut Kaiser -// Copyright (c) 2011 Bryce Lelbach -// Copyright (c) 2011 Thomas Heller -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef HPX_RUNTIME_ACTIONS_DETAIL_REMOTE_ACTION_RESULT_HPP -#define HPX_RUNTIME_ACTIONS_DETAIL_REMOTE_ACTION_RESULT_HPP - -namespace hpx { namespace actions { namespace detail -{ - template - struct remote_action_result - { - typedef Result type; - }; - -}}} - -#endif diff --git a/hpx/runtime/components/client_base.hpp b/hpx/runtime/components/client_base.hpp index f3ee9fcc0807..dbbdeff35070 100644 --- a/hpx/runtime/components/client_base.hpp +++ b/hpx/runtime/components/client_base.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -121,6 +122,14 @@ namespace hpx { namespace traits typename std::enable_if::value>::type> : shared_state_ptr::type> {}; + + /////////////////////////////////////////////////////////////////////// + template + struct action_remote_result_customization_point::value>::type> + { + typedef id_type type; + }; } }} diff --git a/hpx/runtime/trigger_lco.hpp b/hpx/runtime/trigger_lco.hpp index eda141afc9b9..ca20e0bcc148 100644 --- a/hpx/runtime/trigger_lco.hpp +++ b/hpx/runtime/trigger_lco.hpp @@ -132,7 +132,10 @@ namespace hpx /// send all credits in \a id along with the generated /// message. The default value is \a true. template - void set_lco_value(naming::id_type const& id, Result && t, + typename std::enable_if< + !std::is_same::type, naming::address>::value + >::type + set_lco_value(naming::id_type const& id, Result && t, naming::id_type const& cont, bool move_credits = true) { set_lco_value(id, naming::address(), std::forward(t), cont, diff --git a/hpx/traits/action_remote_result.hpp b/hpx/traits/action_remote_result.hpp new file mode 100644 index 000000000000..c0a40b48cb21 --- /dev/null +++ b/hpx/traits/action_remote_result.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2014 Hartmut Kaiser +// Copyright (c) 2011 Bryce Lelbach +// Copyright (c) 2011 Thomas Heller +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef HPX_TRAITS_ACTION_REMOTE_RESULT_HPP +#define HPX_TRAITS_ACTION_REMOTE_RESULT_HPP + +namespace hpx { namespace traits +{ + namespace detail + { + template + struct action_remote_result_customization_point + { + typedef Result type; + }; + } + + template + struct action_remote_result + : detail::action_remote_result_customization_point + {}; +}} + +#endif diff --git a/tests/regressions/components/CMakeLists.txt b/tests/regressions/components/CMakeLists.txt index 5558b5b79cfa..4953a45bf94d 100644 --- a/tests/regressions/components/CMakeLists.txt +++ b/tests/regressions/components/CMakeLists.txt @@ -5,6 +5,7 @@ set(tests moveonly_constructor_arguments_1405 + returned_client_2150 ) foreach(test ${tests}) diff --git a/tests/regressions/components/returned_client_2150.cpp b/tests/regressions/components/returned_client_2150.cpp new file mode 100644 index 000000000000..63f2df26d360 --- /dev/null +++ b/tests/regressions/components/returned_client_2150.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2016 Christopher Hinz +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// verify #2150 is fixed (Unable to use component clients as action return types) + +#include +#include +#include + +#include + +class foo_server : public hpx::components::component_base +{ +}; + +typedef hpx::components::component server_type; +HPX_REGISTER_COMPONENT(server_type, foo_server); + +class foo : public hpx::components::client_base +{ +public: + typedef hpx::components::client_base base_type; + + foo() {} + foo(hpx::future&& id) : base_type(std::move(id)) {} +}; + +foo get_foo() +{ + return hpx::new_(hpx::find_here()); +} + +HPX_PLAIN_ACTION(get_foo, get_foo_action); + +hpx::future get_future_id() +{ + return hpx::new_(hpx::find_here()); +} + +HPX_PLAIN_ACTION(get_future_id, get_future_id_action); + +int hpx_main(int, char*[]) +{ + { + auto result1 = get_foo_action()(hpx::find_here()); + auto result2 = get_future_id_action()(hpx::find_here()); + + auto result3 = hpx::async(hpx::find_here()).get(); + auto result4 = hpx::async(hpx::find_here()).get(); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + return hpx::init(argc, argv); +}