1 /*
2  * SObjectizer-5
3  */
4 
5 /*!
6  * \since
7  * v.5.5.3
8  *
9  * \file
10  * \brief An interface of subscription storage.
11  */
12 
13 #pragma once
14 
15 #include <ostream>
16 #include <sstream>
17 #include <vector>
18 
19 #include <so_5/types.hpp>
20 
21 #include <so_5/mbox.hpp>
22 #include <so_5/state.hpp>
23 #include <so_5/execution_demand.hpp>
24 #include <so_5/subscription_storage_fwd.hpp>
25 
26 namespace so_5
27 {
28 
29 namespace impl
30 {
31 
32 //
33 // event_handler_data_t
34 //
35 /*!
36  * \since
37  * v.5.4.0
38  *
39  * \brief Information about event_handler and its properties.
40  */
41 struct event_handler_data_t
42 	{
43 		//! Method for handling event.
44 		event_handler_method_t m_method;
45 		//! Is event handler thread safe or not.
46 		thread_safety_t m_thread_safety;
47 		//! Kind of this event handler.
48 		/*!
49 		 * \since
50 		 * v.5.7.0
51 		 */
52 		event_handler_kind_t m_kind;
53 
event_handler_data_tso_5::impl::event_handler_data_t54 		event_handler_data_t(
55 			event_handler_method_t method,
56 			thread_safety_t thread_safety,
57 			event_handler_kind_t kind )
58 			:	m_method( std::move( method ) )
59 			,	m_thread_safety( thread_safety )
60 			,	m_kind( kind )
61 			{}
62 	};
63 
64 /*!
65  * \since
66  * v.5.5.3
67  *
68  * \brief Common stuff for various subscription storage implementations.
69  */
70 namespace subscription_storage_common
71 {
72 
73 /*!
74  * \since
75  * v.5.5.3
76  *
77  * \brief An information about one subscription.
78  */
79 struct subscr_info_t
80 	{
81 		//! Reference to mbox.
82 		/*!
83 		 * Reference must be stored because we must have
84 		 * access to mbox during destroyment of all
85 		 * subscriptions in destructor.
86 		 */
87 		mbox_t m_mbox;
88 		std::type_index m_msg_type;
89 		const state_t * m_state;
90 		event_handler_data_t m_handler;
91 
subscr_info_tso_5::impl::subscription_storage_common::subscr_info_t92 		subscr_info_t(
93 			mbox_t mbox,
94 			std::type_index msg_type,
95 			const state_t & state,
96 			const event_handler_method_t & method,
97 			thread_safety_t thread_safety,
98 			event_handler_kind_t handler_kind )
99 			:	m_mbox( std::move( mbox ) )
100 			,	m_msg_type( std::move( msg_type ) )
101 			,	m_state( &state )
102 			,	m_handler( method, thread_safety, handler_kind )
103 			{}
104 	};
105 
106 /*!
107  * \since
108  * v.5.5.3
109  *
110  * \brief Type of vector with subscription information.
111  */
112 using subscr_info_vector_t = std::vector< subscr_info_t >;
113 
114 /*!
115  * \since
116  * v.5.5.3
117  *
118  * \brief A helper function for creating subscription description.
119  */
120 inline std::string
make_subscription_description(const mbox_t & mbox_ref,std::type_index msg_type,const state_t & state)121 make_subscription_description(
122 	const mbox_t & mbox_ref,
123 	std::type_index msg_type,
124 	const state_t & state )
125 	{
126 		std::ostringstream s;
127 		s << "(mbox:'" << mbox_ref->query_name()
128 			<< "', msg_type:'" << msg_type.name() << "', state:'"
129 			<< state.query_name() << "')";
130 
131 		return s.str();
132 	}
133 
134 } /* namespace subscription_storage_common */
135 
136 /*!
137  * \since
138  * v.5.5.3
139  *
140  * \brief An interface of subscription storage
141  *
142  * Prior to v.5.5.3 there where only one subscription_storage implementation.
143  * But this implementation was not efficient for all cases.
144  *
145  * Sometimes an agent has very few subscriptions and efficient
146  * implementation for that case can be based on std::vector.
147  * Sometimes an agent has very many subscriptions and efficient
148  * implementation can require std::map or std::unordered_map.
149  *
150  * The purpose of this interface is hiding details of concrete
151  * subscription_storage implementation.
152  */
153 class subscription_storage_t
154 	{
155 	public :
156 		subscription_storage_t( agent_t * owner );
157 		virtual ~subscription_storage_t() noexcept = default;
158 
159 		virtual void
160 		create_event_subscription(
161 			const mbox_t & mbox,
162 			const std::type_index & msg_type,
163 			const message_limit::control_block_t * limit,
164 			const state_t & target_state,
165 			const event_handler_method_t & method,
166 			thread_safety_t thread_safety,
167 			event_handler_kind_t handler_kind ) = 0;
168 
169 		virtual void
170 		drop_subscription(
171 			const mbox_t & mbox,
172 			const std::type_index & msg_type,
173 			const state_t & target_state ) = 0;
174 
175 		virtual void
176 		drop_subscription_for_all_states(
177 			const mbox_t & mbox,
178 			const std::type_index & msg_type ) = 0;
179 
180 		virtual const event_handler_data_t *
181 		find_handler(
182 			mbox_id_t mbox_id,
183 			const std::type_index & msg_type,
184 			const state_t & current_state ) const noexcept = 0;
185 
186 		virtual void
187 		debug_dump( std::ostream & to ) const = 0;
188 
189 		//! Drop all content.
190 		/*!
191 		 * All information about subscription must be erased,
192 		 * but without real unsubscription.
193 		 *
194 		 * This method will be called after successful copy of
195 		 * subscription information to another storage.
196 		 */
197 		virtual void
198 		drop_content() = 0;
199 
200 		//! Get content for copying subscription information
201 		//! to another storage object.
202 		virtual subscription_storage_common::subscr_info_vector_t
203 		query_content() const = 0;
204 
205 		//! Setup content from information from another storage object.
206 		virtual void
207 		setup_content(
208 			subscription_storage_common::subscr_info_vector_t && info ) = 0;
209 
210 		//! Count of subscriptions in the storage.
211 		virtual std::size_t
212 		query_subscriptions_count() const = 0;
213 
214 	protected :
215 		agent_t *
216 		owner() const;
217 
218 	private :
219 		agent_t * m_owner;
220 	};
221 
222 } /* namespace impl */
223 
224 } /* namespace so_5 */
225 
226