1 /*
2  * Test of resending the same message as a mutable.
3  */
4 
5 #include <so_5/all.hpp>
6 
7 #include <test/3rd_party/various_helpers/time_limited_execution.hpp>
8 #include <test/3rd_party/various_helpers/ensure.hpp>
9 
10 struct message final : public so_5::message_t
11 {
12 	std::string m_value;
13 
messagemessage14 	message( std::string value ) : m_value{ std::move(value) } {}
15 };
16 
17 class first_sender_t final : public so_5::agent_t
18 {
19 public :
first_sender_t(context_t ctx,so_5::mbox_t second)20 	first_sender_t( context_t ctx, so_5::mbox_t second )
21 		:	so_5::agent_t{ std::move(ctx) }
22 		,	m_second{ std::move(second) }
23 		,	m_message{ std::piecewise_construct, "hello!" }
24 	{}
25 
26 	void
so_evt_start()27 	so_evt_start() override
28 	{
29 		so_5::send( m_second, std::move(m_message) );
30 	}
31 
32 private :
33 	const so_5::mbox_t m_second;
34 	so_5::message_holder_t< so_5::mutable_msg< message > > m_message;
35 };
36 
37 class second_sender_t final : public so_5::agent_t
38 {
39 public :
second_sender_t(context_t ctx,so_5::mbox_t third)40 	second_sender_t( context_t ctx, so_5::mbox_t third )
41 		:	so_5::agent_t{ std::move(ctx) }
42 		,	m_third{ std::move(third) }
43 	{
44 		so_subscribe_self().event( &second_sender_t::on_message );
45 	}
46 
47 private :
48 	const so_5::mbox_t m_third;
49 
50 	void
on_message(so_5::mutable_mhood_t<message> cmd)51 	on_message( so_5::mutable_mhood_t<message> cmd )
52 	{
53 		cmd->m_value += "!";
54 		so_5::send( m_third, std::move(cmd) );
55 	}
56 };
57 
58 class third_sender_t final : public so_5::agent_t
59 {
60 	struct resend final : public so_5::signal_t {};
61 
62 public :
third_sender_t(context_t ctx,so_5::mbox_t fourth)63 	third_sender_t( context_t ctx, so_5::mbox_t fourth )
64 		:	so_5::agent_t{ std::move(ctx) }
65 		,	m_fourth{ std::move(fourth) }
66 	{
67 		so_subscribe_self()
68 			.event( &third_sender_t::on_message )
69 			.event( &third_sender_t::on_resend );
70 	}
71 
72 private :
73 	const so_5::mbox_t m_fourth;
74 	so_5::message_holder_t< so_5::mutable_msg<message> > m_message;
75 
76 	void
on_message(so_5::mutable_mhood_t<message> cmd)77 	on_message( so_5::mutable_mhood_t<message> cmd )
78 	{
79 		cmd->m_value += "!";
80 		m_message = cmd.make_holder();
81 
82 		so_5::send<resend>( *this );
83 	}
84 
85 	void
on_resend(so_5::mhood_t<resend>)86 	on_resend( so_5::mhood_t<resend> )
87 	{
88 		so_5::send( m_fourth, std::move(m_message) );
89 	}
90 };
91 
92 class last_t final : public so_5::agent_t
93 {
94 public :
last_t(context_t ctx)95 	last_t( context_t ctx ) : so_5::agent_t{ std::move(ctx) }
96 	{
97 		so_subscribe_self().event( &last_t::on_message );
98 	}
99 
100 private :
101 	void
on_message(so_5::mutable_mhood_t<message> cmd)102 	on_message( so_5::mutable_mhood_t<message> cmd )
103 	{
104 		ensure_or_die( cmd->m_value == "hello!!!",
105 				"unexpected value: " + cmd->m_value );
106 
107 		so_deregister_agent_coop_normally();
108 	}
109 };
110 
111 int
main()112 main()
113 {
114 	run_with_time_limit( [] {
115 			so_5::launch(
116 				[]( so_5::environment_t & env )
117 				{
118 					env.introduce_coop( []( so_5::coop_t & coop ) {
119 							auto last = coop.make_agent< last_t >();
120 							auto third = coop.make_agent< third_sender_t >(
121 									last->so_direct_mbox() );
122 							auto second = coop.make_agent< second_sender_t >(
123 									third->so_direct_mbox() );
124 							coop.make_agent< first_sender_t >(
125 									second->so_direct_mbox() );
126 						} );
127 				} );
128 		},
129 		10 );
130 
131 	return 0;
132 }
133 
134