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