1 /*
2 * Test for various variants of environment_t::introduce_coop.
3 */
4
5 #include <iostream>
6 #include <map>
7 #include <exception>
8
9 #include <so_5/all.hpp>
10
11 #include <test/3rd_party/various_helpers/time_limited_execution.hpp>
12 #include <test/3rd_party/various_helpers/ensure.hpp>
13
14 using namespace std::string_literals;
15
16 // This is non-copyable and non-movable type.
17 class test_object_t
18 {
19 public:
20 test_object_t() = default;
21 test_object_t( const test_object_t & ) = delete;
22 test_object_t( test_object_t && ) = delete;
23 };
24
25 test_object_t g_test_object;
26
27 so_5::mbox_t
manager_mbox(so_5::environment_t & env)28 manager_mbox( so_5::environment_t & env )
29 {
30 return env.create_mbox( "manager" );
31 }
32
33 struct msg_started : public so_5::signal_t {};
34
35 class a_manager_t : public so_5::agent_t
36 {
37 public :
a_manager_t(context_t ctx,unsigned int expected)38 a_manager_t(
39 context_t ctx,
40 unsigned int expected )
41 : so_5::agent_t( ctx )
42 , m_expected( expected )
43 {}
44
45 virtual void
so_define_agent()46 so_define_agent() override
47 {
48 so_default_state().event(
49 manager_mbox( so_environment() ),
50 [this](mhood_t< msg_started >) {
51 ++m_received;
52 if( m_received == m_expected )
53 so_environment().stop();
54 } );
55 }
56
57 private :
58 const unsigned int m_expected;
59 unsigned int m_received = { 0 };
60 };
61
62 void
define_agent(so_5::coop_t & coop)63 define_agent(
64 so_5::coop_t & coop )
65 {
66 class a_starter_t final : public so_5::agent_t
67 {
68 public:
69 using so_5::agent_t::agent_t;
70
71 void so_evt_start() override
72 {
73 so_5::send< msg_started >( manager_mbox( so_environment() ) );
74 }
75 };
76
77 coop.make_agent< a_starter_t >();
78 }
79
80 void
ensure_valid_value(test_object_t && actual)81 ensure_valid_value(
82 test_object_t && actual )
83 {
84 ensure_or_die( std::addressof(actual) == std::addressof(g_test_object),
85 "invalid address received!" );
86 }
87
88 class a_child_owner_t : public so_5::agent_t
89 {
90 public :
a_child_owner_t(context_t ctx)91 a_child_owner_t( context_t ctx )
92 : so_5::agent_t( ctx )
93 {}
94
95 virtual void
so_evt_start()96 so_evt_start() override
97 {
98 using namespace so_5;
99
100 auto & env = so_environment();
101
102 // Special check for C++14
103 ensure_valid_value(
104 introduce_child_coop( *this,
105 []( auto & coop ) -> test_object_t && {
106 std::cout << "introduce_child_coop in C++14 or later." << std::endl;
107 define_agent( coop );
108 return std::move(g_test_object);
109 } ) );
110
111 ensure_valid_value(
112 introduce_child_coop( *this,
113 so_5::disp::active_obj::make_dispatcher( env ).binder(),
114 []( coop_t & coop ) -> test_object_t && {
115 define_agent( coop );
116 return std::move(g_test_object);
117 } ) );
118 }
119 };
120
121 void
init(so_5::environment_t & env)122 init( so_5::environment_t & env )
123 {
124 using namespace so_5;
125
126 env.register_agent_as_coop( env.make_agent< a_manager_t >( 4u ) );
127 env.register_agent_as_coop( env.make_agent< a_child_owner_t >() );
128
129 ensure_valid_value(
130 env.introduce_coop(
131 []( auto & coop ) -> test_object_t && {
132 std::cout << "introduce_coop in C++14 or later." << std::endl;
133 define_agent( coop );
134 return std::move(g_test_object);
135 } ) );
136
137 ensure_valid_value(
138 env.introduce_coop(
139 so_5::disp::active_obj::make_dispatcher( env ).binder(),
140 []( coop_t & coop ) -> test_object_t && {
141 define_agent( coop );
142 return std::move(g_test_object);
143 } ) );
144 }
145
146 int
main()147 main()
148 {
149 try
150 {
151 run_with_time_limit(
152 []()
153 {
154 so_5::launch( &init );
155 },
156 20,
157 "introduce_coop test" );
158 }
159 catch( const std::exception & ex )
160 {
161 std::cerr << "error: " << ex.what() << std::endl;
162 return 1;
163 }
164
165 return 0;
166 }
167
168