1 // Copyright (c) 2013 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 // This test case demonstrates the issue described in #588: Continuations do not 7 // keep object alive 8 9 #include <hpx/hpx.hpp> 10 #include <hpx/hpx_main.hpp> 11 #include <hpx/include/actions.hpp> 12 #include <hpx/util/lightweight_test.hpp> 13 14 #include <vector> 15 16 /////////////////////////////////////////////////////////////////////////////// 17 struct test_server 18 : hpx::components::simple_component_base<test_server> 19 { ~test_servertest_server20 ~test_server() 21 { 22 } 23 24 hpx::id_type create_new(hpx::id_type const& id) const; 25 26 HPX_DEFINE_COMPONENT_ACTION(test_server, create_new, create_new_action); 27 }; 28 29 typedef hpx::components::simple_component<test_server> server_type; 30 HPX_REGISTER_COMPONENT(server_type, test_server); 31 32 typedef test_server::create_new_action create_new_action; 33 HPX_REGISTER_ACTION_DECLARATION(create_new_action); 34 HPX_REGISTER_ACTION(create_new_action); 35 36 struct test_client 37 : hpx::components::client_base< 38 test_client, hpx::components::stub_base<test_server> > 39 { 40 typedef hpx::components::client_base< 41 test_client, hpx::components::stub_base<test_server> > 42 client_base_type; 43 44 // create a new instance of a test_server test_clienttest_client45 test_client() 46 {} 47 48 // initialize the client from a given server instance test_clienttest_client49 explicit test_client(hpx::id_type const& id) 50 : client_base_type(id) 51 {} test_clienttest_client52 explicit test_client(hpx::shared_future<hpx::id_type> const& fgid) 53 : client_base_type(fgid) 54 {} 55 create_newtest_client56 test_client create_new(hpx::id_type const& id) const 57 { 58 create_new_action new_; 59 return test_client(hpx::async(new_, this->get_id(), id)); 60 } 61 }; 62 63 // ask the server to create a new instance create_new(hpx::id_type const & id) const64hpx::id_type test_server::create_new(hpx::id_type const& id) const 65 { 66 // this waits for the new object to be created 67 return test_client::create(id).get_id(); 68 } 69 main()70int main() 71 { 72 std::vector<hpx::id_type> localities = hpx::find_all_localities(); 73 74 for (hpx::id_type const& id : localities) 75 { 76 // repeating this a couple of times forces the issue ... 77 for (int i = 0; i != 100; ++i) 78 { 79 test_client c = test_client::create(id); // create a new instance 80 81 // this construct overwrites the original client with a newly created 82 // one which causes the only reference to the initial test_server to go 83 // out of scope too early. 84 c = c.create_new(id); 85 86 // the new instance 'c' goes out of scope here, which makes the future 87 // holding the only reference to the second server instance disappear 88 } 89 } 90 91 return hpx::util::report_errors(); 92 } 93