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
45
46
47
48
53 std::size_t initial_capacity );
58 const mbox_t & mbox_ref,
59 const std::type_index & type_index,
62 const event_handler_method_t & method,
69 const std::type_index & msg_type,
70 const state_t & target_state )
noexcept override;
75 const std::type_index & msg_type )
noexcept override;
83 const std::type_index & msg_type,
84 const state_t & current_state )
const noexcept override;
87 debug_dump( std::ostream & to )
const override;
97 subscription_storage_common::subscr_info_vector_t && info )
override;
117 return m_id == info.m_mbox->id() &&
118 m_type == info.m_msg_type;
131 template<
class Container >
134 const mbox_id_t & mbox_id,
135 const std::type_index & msg_type,
136 const state_t & target_state ) ->
decltype( c.begin() )
140 return find_if( begin( c ), end( c ),
141 [&](
typename Container::value_type
const & o ) {
142 return ( o.m_mbox->id() == mbox_id &&
143 o.m_msg_type == msg_type &&
144 o.m_state == &target_state );
151 std::size_t initial_capacity )
153 m_events.reserve( initial_capacity );
164 const std::type_index & msg_type,
167 const event_handler_method_t & method,
174 const auto mbox_id = mbox->id();
177 bool has_subscriptions_from_that_mbox =
false;
178 for(
auto it = m_events.begin(), it_end = m_events.end();
181 if( it->m_mbox->id() == mbox_id &&
182 it->m_msg_type == msg_type )
184 has_subscriptions_from_that_mbox =
true;
185 if( it->m_state == std::addressof(target_state) )
187 rc_evt_handler_already_provided,
188 "agent is already subscribed to message, " +
189 make_subscription_description(
199 m_events.emplace_back(
211 if( !has_subscriptions_from_that_mbox )
216 mbox->subscribe_event_handler(
229 const std::type_index & msg_type,
230 const state_t & target_state )
noexcept
234 const auto mbox_id = mbox->id();
238 std::size_t number_of_subscriptions{};
239 subscr_info_vector_t::iterator it = m_events.begin();
240 subscr_info_vector_t::iterator it_end = m_events.end();
242 for(; it != it_end; ++it )
244 if( it->m_mbox->id() == mbox_id &&
245 it->m_msg_type == msg_type )
247 ++number_of_subscriptions;
248 if( it->m_state == std::addressof(target_state) )
259 it = m_events.erase( it );
260 --number_of_subscriptions;
268 if( !number_of_subscriptions )
271 if( m_events.end() != std::find_if( it, m_events.end(),
272 is_same_mbox_msg{ mbox_id, msg_type } ) )
273 number_of_subscriptions = 1;
278 if( !number_of_subscriptions )
283 mbox->unsubscribe_event_handler( msg_type, message_sink );
291 const std::type_index & msg_type )
noexcept
295 const auto predicate = is_same_mbox_msg{ mbox->id(), msg_type };
297 find_if( begin( m_events ), end( m_events ), predicate );
298 it != end( m_events ) )
303 auto & message_sink = it->m_message_sink.get();
307 remove_if( it, end( m_events ), predicate ),
313 mbox->unsubscribe_event_handler( msg_type, message_sink );
326 const std::type_index & msg_type,
327 const state_t & current_state )
const noexcept
329 auto it = find( m_events, mbox_id, msg_type, current_state );
331 if( it != std::end( m_events ) )
332 return &(it->m_handler);
340 for(
const auto & e : m_events )
341 to <<
"{" << e.m_mbox->id() <<
", "
342 << e.m_msg_type.name() <<
", "
343 << e.m_state->query_name() <<
"}"
350 if( m_events.empty() )
360 sort( begin( m_events ), end( m_events ),
361 [](
const auto & a,
const auto & b )
363 return a.m_mbox->id() < b.m_mbox->id() ||
364 ( a.m_mbox->id() == b.m_mbox->id() &&
365 a.m_msg_type < b.m_msg_type );
371 const auto total_items = m_events.size();
372 for( std::size_t i = 0u; i < total_items; )
374 auto & current_info = m_events[ i ];
375 current_info.m_mbox->unsubscribe_event_handler(
376 current_info.m_msg_type,
377 current_info.m_message_sink );
382 for( ; (i+j) < total_items; ++j )
384 const auto & next_info = m_events[ i+j ];
385 if( current_info.m_mbox->id() != next_info.m_mbox->id() ||
386 current_info.m_msg_type != next_info.m_msg_type )
413 subscription_storage_common::subscr_info_vector_t && info )
415 m_events = std::move( info );
421 return m_events.size();
432 return [initial_capacity]() {
433 return impl::subscription_storage_unique_ptr_t(
434 new impl::vector_based_subscr_storage::storage_t(
435 initial_capacity ) );
Interface for message sink.
An interface of subscription storage.
A vector-based storage for agent's subscriptions information.
void drop_all_subscriptions() noexcept override
Drop all subscriptions.
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
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
subscription_storage_common::subscr_info_vector_t query_content() const override
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
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
storage_t(std::size_t initial_capacity)
subscr_info_vector_t m_events
Subscription information.
void drop_content() noexcept override
Drop all content.
std::size_t query_subscriptions_count() const override
Count of subscriptions in the storage.
virtual void drop_subscription(const mbox_t &mbox, const std::type_index &msg_type, const state_t &target_state) noexcept override
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.
Common stuff for various subscription storage implementations.
auto find(Container &c, const mbox_id_t &mbox_id, const std::type_index &msg_type, const state_t &target_state) -> decltype(c.begin())
A vector-based storage for agent's subscriptions information.
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 vector_based_subscription_storage_factory(std::size_t initial_capacity)
Factory for subscription storage based on unsorted std::vector.
event_handler_kind_t
Kind of an event handler.
Information about event_handler and its properties.
An information about one subscription.
const std::type_index & m_type
bool operator()(const info_t &info) const