2
3
6
7
8
9
10
11
13#include <so_5/impl/subscription_storage_iface.hpp>
19#include <so_5/details/rollback_on_exception.hpp>
28
29
30
31
32
37
38
39
40
41
42
43
44
53 const mbox_t & mbox_ref,
54 const std::type_index & type_index,
57 const event_handler_method_t & method,
64 const std::type_index & msg_type,
65 const state_t & target_state )
noexcept override;
70 const std::type_index & msg_type )
noexcept override;
78 const std::type_index & msg_type,
79 const state_t & current_state )
const noexcept override;
82 debug_dump( std::ostream & to )
const override;
92 subscription_storage_common::subscr_info_vector_t && info )
override;
107 std::type_index msg_type,
121 if( m_msg_type < o.m_msg_type )
123 else if( m_msg_type == o.m_msg_type )
136
137
138
139
143
144
148
149
169 const mbox_id_t & mbox_id,
170 const std::type_index & msg_type,
171 const state_t & target_state ) ->
decltype( c.begin() )
173 return c.find(
typename C::key_type {
174 mbox_id, msg_type, &target_state } );
191 template<
class M,
class IT >
196 const is_same_mbox_msg predicate{
197 it->first.m_mbox_id, it->first.m_msg_type };
199 if( it != s.begin() )
201 IT prev = std::prev( it );
202 if( predicate( prev->first ) )
206 IT next = std::next( it );
207 if( next != s.end() )
208 return predicate( next->first );
226 const std::type_index & msg_type,
229 const event_handler_method_t & method,
236 const auto mbox_id = mbox->id();
239 auto existed_position = find(
240 m_events, mbox_id, msg_type, target_state );
242 if( existed_position != m_events.end() )
244 rc_evt_handler_already_provided,
245 "agent is already subscribed to message, " +
246 make_subscription_description( mbox, msg_type, target_state ) );
249 auto ins_result = m_events.emplace(
250 key_t { mbox_id, msg_type, &target_state },
253 std::ref( message_sink ),
254 event_handler_data_t {
268 if( !is_known_mbox_msg_pair( m_events, ins_result.first ) )
272 mbox->subscribe_event_handler(
277 m_events.erase( ins_result.first );
285 const std::type_index & msg_type,
286 const state_t & target_state )
noexcept
288 auto existed_position = find(
289 m_events, mbox->id(), msg_type, target_state );
290 if( existed_position != m_events.end() )
299 bool must_unsubscribe_mbox =
300 !is_known_mbox_msg_pair( m_events, existed_position );
306 m_events.erase( existed_position );
308 if( must_unsubscribe_mbox )
310 mbox->unsubscribe_event_handler( msg_type, sink );
318 const std::type_index & msg_type )
noexcept
322 auto lower_bound = m_events.lower_bound(
323 key_t{ mbox->id(), msg_type,
nullptr } );
325 auto need_erase = [&] {
326 return lower_bound != std::end(m_events) &&
327 is_same( lower_bound->first );
329 const bool events_found = need_erase();
340 m_events.erase( lower_bound++ );
342 while( need_erase() );
348 mbox->unsubscribe_event_handler( msg_type, sink );
361 const std::type_index & msg_type,
362 const state_t & current_state )
const noexcept
364 auto it = find( m_events, mbox_id, msg_type, current_state );
366 if( it != std::end( m_events ) )
367 return &(it->second.m_handler);
375 for(
const auto & e : m_events )
376 to <<
"{" << e.first.m_mbox_id <<
", "
377 << e.first.m_msg_type.name() <<
", "
378 << e.first.m_state->query_name() <<
"}"
387 auto it = begin( m_events );
388 while( it != end( m_events ) )
392 if( it == end( m_events ) || !is_same_mbox_msg{
393 cur->first.m_mbox_id,
394 cur->first.m_msg_type }( it->first ) )
396 cur->second.m_mbox->unsubscribe_event_handler(
397 cur->first.m_msg_type,
398 cur->second.m_message_sink.get() );
401 m_events.erase( cur );
417 subscr_info_vector_t result;
419 if( !m_events.empty() )
421 result.reserve( m_events.size() );
423 transform( begin( m_events ), end( m_events ),
424 back_inserter( result ),
425 [](
const subscr_map_t::value_type & e )
427 return subscr_info_t(
430 e.second.m_message_sink.get(),
432 e.second.m_handler.m_method,
433 e.second.m_handler.m_thread_safety,
434 e.second.m_handler.m_kind );
443 subscription_storage_common::subscr_info_vector_t && info )
449 transform( begin(info), end(info),
450 inserter( events, events.begin() ),
451 [](
const subscr_info_t & i )
453 return subscr_map_t::value_type {
466 swap( m_events, events );
472 return m_events.size();
483 return impl::subscription_storage_unique_ptr_t(
484 new impl::map_based_subscr_storage::storage_t() );
Interface for message sink.
A map-based storage for agent's subscriptions information.
void debug_dump(std::ostream &to) const override
void drop_subscription_for_all_states(const mbox_t &mbox, const std::type_index &msg_type) noexcept override
const event_handler_data_t * find_handler(mbox_id_t mbox_id, const std::type_index &msg_type, const state_t ¤t_state) const noexcept override
void drop_all_subscriptions() noexcept override
Drop all subscriptions.
void drop_content() noexcept override
Drop all content.
void create_event_subscription(const mbox_t &mbox_ref, const std::type_index &type_index, abstract_message_sink_t &message_sink, const state_t &target_state, const event_handler_method_t &method, thread_safety_t thread_safety, event_handler_kind_t handler_kind) override
void setup_content(subscription_storage_common::subscr_info_vector_t &&info) override
Setup content from information from another storage object.
void destroy_all_subscriptions() noexcept
std::size_t query_subscriptions_count() const override
Count of subscriptions in the storage.
void drop_subscription(const mbox_t &mbox, const std::type_index &msg_type, const state_t &target_state) noexcept override
subscription_storage_common::subscr_info_vector_t query_content() const override
subscr_map_t m_events
Subscription information.
An interface of subscription storage.
std::enable_if< details::is_agent_method_pointer< details::method_arity::nullary, Method_Pointer >::value, state_t & >::type on_enter(Method_Pointer pfn)
Set on enter handler.
#define SO_5_THROW_EXCEPTION(error_code, desc)
Some reusable and low-level classes/functions which can be used in public header files.
bool is_known_mbox_msg_pair(M &s, IT it)
auto find(C &c, const mbox_id_t &mbox_id, const std::type_index &msg_type, const state_t &target_state) -> decltype(c.begin())
A map-based storage for agent's subscriptions information.
Common stuff for various subscription storage implementations.
Details of SObjectizer run-time implementations.
Private part of message limit implementation.
thread_safety_t
Thread safety indicator.
SO_5_FUNC subscription_storage_factory_t map_based_subscription_storage_factory()
Factory for subscription storage based on std::map.
event_handler_kind_t
Kind of an event handler.
Information about event_handler and its properties.
bool operator()(const K &k) const
const std::type_index & m_type
Type of key in subscription's map.
bool operator<(const key_t &o) const
std::type_index m_msg_type
key_t(mbox_id_t mbox_id, std::type_index msg_type, const state_t *state)
Type of value for subscription map's item.
const std::reference_wrapper< abstract_message_sink_t > m_message_sink
const mbox_t m_mbox
Reference to mbox.
const event_handler_data_t m_handler