1 /*
2  * SObjectizer-5
3  */
4 
5 /*!
6  * \file
7  * \brief Implementation of some parts of handler makers which can't be inline.
8  *
9  * \since
10  * v.5.5.23
11  */
12 
13 #include <so_5/handler_makers.hpp>
14 
15 #include <so_5/impl/enveloped_msg_details.hpp>
16 
17 namespace so_5 {
18 
19 namespace details {
20 
21 namespace {
22 
23 bool
process_envelope_when_handler_found(const msg_type_and_handler_pair_t & handler,message_ref_t & message)24 process_envelope_when_handler_found(
25 	const msg_type_and_handler_pair_t & handler,
26 	message_ref_t & message )
27 	{
28 		using namespace so_5::enveloped_msg::impl;
29 
30 		bool result = false;
31 
32 		// We don't expect exceptions here and can't restore after them.
33 		so_5::details::invoke_noexcept_code( [&] {
34 			auto & envelope = message_to_envelope( message );
35 
36 			mchain_demand_handler_invoker_t invoker{ handler };
37 			envelope.access_hook(
38 					so_5::enveloped_msg::access_context_t::handler_found,
39 					invoker );
40 
41 			result = invoker.was_handled();
42 		} );
43 
44 		return result;
45 	}
46 
47 } /* namespace anonymous */
48 
49 SO_5_FUNC
50 bool
find_and_use_handler(const msg_type_and_handler_pair_t * left,const msg_type_and_handler_pair_t * right,const std::type_index & msg_type,message_ref_t & message)51 handlers_bunch_basics_t::find_and_use_handler(
52 	const msg_type_and_handler_pair_t * left,
53 	const msg_type_and_handler_pair_t * right,
54 	const std::type_index & msg_type,
55 	message_ref_t & message )
56 	{
57 		bool ret_value = false;
58 
59 		msg_type_and_handler_pair_t key{ msg_type };
60 		auto it = std::lower_bound( left, right, key );
61 		if( it != right && it->m_msg_type == key.m_msg_type )
62 			{
63 				// Handler is found and must be called.
64 				switch( message_kind( message ) )
65 					{
66 					case message_t::kind_t::signal : [[fallthrough]];
67 					case message_t::kind_t::classical_message : [[fallthrough]];
68 					case message_t::kind_t::user_type_message :
69 						// This is an async message.
70 						// Simple call is enough.
71 						ret_value = true;
72 						it->m_handler( message );
73 					break;
74 
75 					case message_t::kind_t::enveloped_msg :
76 						// Invocation must be done a special way.
77 						ret_value = process_envelope_when_handler_found( *it, message );
78 					break;
79 					}
80 			}
81 
82 		return ret_value;
83 	}
84 
85 } /* namespace details */
86 
87 } /* namespace so_5 */
88 
89