2
3
6
7
8
9
10
12#include <so_5/impl/subscription_storage_iface.hpp>
14#include <so_5/details/rollback_on_exception.hpp>
28
29
30
31
32
37
38
39
40
41
42
43
44
45
46
47
52 std::size_t initial_capacity );
57 const mbox_t & mbox_ref,
58 const std::type_index & type_index,
61 const event_handler_method_t & method,
68 const std::type_index & msg_type,
69 const state_t & target_state )
noexcept override;
74 const std::type_index & msg_type )
noexcept override;
82 const std::type_index & msg_type,
83 const state_t & current_state )
const noexcept override;
86 debug_dump( std::ostream & to )
const override;
96 subscription_storage_common::subscr_info_vector_t && info )
override;
108
109
110
111
120 return m_id == info.m_mbox->id() &&
121 m_type == info.m_msg_type;
126
127
128
129
130
131
141
142
143
144
145
146
156 if( a.m_msg_type < b.m_msg_type )
158 else if( a.m_msg_type == b.m_msg_type )
161 using ptr_comparator_t = std::less<
const state_t * >;
162 return ptr_comparator_t{}( a.m_state, b.m_state );
178 operator()(
const info_t & a,
const info_t & b )
const noexcept
193
194
195
196
197
198
199
200
201
202
203
204
205
208 subscr_info_vector_t::iterator it,
216
217
218
219
220
226 return a.m_mbox->id() == b.m_mbox->id()
227 && a.m_msg_type == b.m_msg_type
233
234
235
236
237
242 const std::type_index & msg_type,
243 const state_t * target_state )
noexcept
245 return a.m_mbox->id() == mbox_id
246 && a.m_msg_type == msg_type
247 && a.m_state == target_state
254 std::size_t initial_capacity )
256 m_events.reserve( initial_capacity );
267 const std::type_index & msg_type,
270 const event_handler_method_t & method,
277 info_t info_to_store{
288 auto it = std::lower_bound(
289 m_events.begin(), m_events.end(),
291 key_info_comparator_t{} );
292 if( it != m_events.end() && is_equal( *it, info_to_store ) )
295 rc_evt_handler_already_provided,
296 "agent is already subscribed to message, " +
297 make_subscription_description( mbox, msg_type, target_state ) );
300 it = m_events.insert( it, std::move(info_to_store) );
305 const bool info_for_mbox_msg_type_exists =
306 check_presence_of_mbox_msg_type_info_around_it(
308 is_same_mbox_msg_t{ mbox->id(), msg_type } );
314 if( !info_for_mbox_msg_type_exists )
319 mbox->subscribe_event_handler(
324 m_events.erase( it );
332 const std::type_index & msg_type,
333 const state_t & target_state )
noexcept
337 auto existed_position = std::lower_bound(
338 m_events.begin(), m_events.end(),
339 key_info_t{ mbox->id(), msg_type, std::addressof(target_state) },
340 key_info_comparator_t{} );
341 if( existed_position != m_events.end()
342 && is_equal( *existed_position,
343 mbox->id(), msg_type, std::addressof(target_state) ) )
347 existed_position->m_message_sink.get();
352 const bool info_for_mbox_msg_type_exists =
353 check_presence_of_mbox_msg_type_info_around_it(
355 is_same_mbox_msg_t{ mbox->id(), msg_type } );
358 m_events.erase( existed_position );
366 if( !info_for_mbox_msg_type_exists )
371 mbox->unsubscribe_event_handler( msg_type, message_sink );
379 const std::type_index & msg_type )
noexcept
383 const auto predicate = is_same_mbox_msg_t{ mbox->id(), msg_type };
384 if(
auto it = std::lower_bound( m_events.begin(), m_events.end(),
386 key_info_t{ mbox->id(), msg_type,
nullptr },
387 key_info_comparator_t{} );
388 it != m_events.end() && predicate( *it ) )
393 auto & message_sink = it->m_message_sink.get();
397 remove_if( it, end( m_events ), predicate ),
403 mbox->unsubscribe_event_handler( msg_type, message_sink );
416 const std::type_index & msg_type,
417 const state_t & current_state )
const noexcept
419 auto existed_position = std::lower_bound(
420 m_events.begin(), m_events.end(),
421 key_info_t{ mbox_id, msg_type, std::addressof(current_state) },
422 key_info_comparator_t{} );
423 if( existed_position != m_events.end()
424 && is_equal( *existed_position,
425 mbox_id, msg_type, std::addressof(current_state) ) )
427 return std::addressof(existed_position->m_handler);
436 for(
const auto & e : m_events )
437 to <<
"{" << e.m_mbox->id() <<
", "
438 << e.m_msg_type.name() <<
", "
439 << e.m_state->query_name() <<
"}"
446 if( m_events.empty() )
451 const auto total_items = m_events.size();
452 for( std::size_t i = 0u; i < total_items; )
454 auto & current_info = m_events[ i ];
455 current_info.m_mbox->unsubscribe_event_handler(
456 current_info.m_msg_type,
457 current_info.m_message_sink );
462 for( ; (i+j) < total_items; ++j )
464 const auto & next_info = m_events[ i+j ];
465 if( current_info.m_mbox->id() != next_info.m_mbox->id() ||
466 current_info.m_msg_type != next_info.m_msg_type )
479 subscr_info_vector_t::iterator it,
483 if( it != m_events.begin() )
484 result = predicate( *(std::prev(it)) );
488 if(
auto next = std::next(it); next != m_events.end() )
489 result = predicate( *(std::next(it)) );
509 subscription_storage_common::subscr_info_vector_t && info )
511 m_events = std::move( info );
512 std::sort( m_events.begin(), m_events.end(), key_info_comparator_t{} );
518 return m_events.size();
529 return [initial_capacity]() {
530 return impl::subscription_storage_unique_ptr_t(
531 new impl::flat_set_based_subscr_storage::storage_t(
532 initial_capacity ) );
Interface for message sink.
A flat-set based storage for agent's subscriptions information.
subscription_storage_common::subscr_info_vector_t query_content() const override
virtual 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
subscr_info_vector_t m_events
Subscription information.
void setup_content(subscription_storage_common::subscr_info_vector_t &&info) override
Setup content from information from another storage object.
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
virtual void drop_subscription(const mbox_t &mbox, const std::type_index &msg_type, const state_t &target_state) noexcept override
storage_t(std::size_t initial_capacity)
void drop_content() noexcept override
Drop all content.
std::size_t query_subscriptions_count() const override
Count of subscriptions in the storage.
bool check_presence_of_mbox_msg_type_info_around_it(subscr_info_vector_t::iterator it, const is_same_mbox_msg_t &predicate) const noexcept
Helper for checking presence of subscriptions for the same message from the same mbox.
void debug_dump(std::ostream &to) const override
void destroy_all_subscriptions() noexcept
void drop_subscription_for_all_states(const mbox_t &mbox, const std::type_index &msg_type) noexcept override
void drop_all_subscriptions() noexcept override
Drop all subscriptions.
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_equal(const subscription_storage_common::subscr_info_t &a, const subscription_storage_common::subscr_info_t &b) noexcept
Helper to check if two objects are for the same subscription.
bool is_equal(const subscription_storage_common::subscr_info_t &a, mbox_id_t mbox_id, const std::type_index &msg_type, const state_t *target_state) noexcept
Helper to check if subscription information the same.
A flat-set 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.
SO_5_FUNC subscription_storage_factory_t flat_set_based_subscription_storage_factory(std::size_t initial_capacity)
Factory for subscription storage based on sorted std::vector.
thread_safety_t
Thread safety indicator.
event_handler_kind_t
Kind of an event handler.
Information about event_handler and its properties.
A helper predicate for searching the same mbox and message type pairs.
bool operator()(const info_t &info) const noexcept
const std::type_index & m_type
A helper predicate for searching specific subscription.
bool operator()(const info_t &a, const info_t &b) const noexcept
bool operator()(const info_t &a, const key_info_t &b) const noexcept
bool operator()(const key_info_t &a, const key_info_t &b) const noexcept
Helper type for storing only key information about a subscription.
const std::type_index & m_msg_type
An information about one subscription.