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) const64 hpx::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()70 int 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