void storage_t::drop_subscription( const mbox_t & mbox, const std::type_index & msg_type, const state_t & target_state ) { auto existed_position = find( m_events, mbox->id(), msg_type, target_state ); if( existed_position != m_events.end() ) { // Note v.5.5.9 unsubscribe_event_handlers is called for // mbox even if it is MPSC mbox. It is necessary for the case // of message delivery tracing. // We must destroy mbox subscription in case if the agent has no // more subscriptions for that mbox+msg_type pair. // Detect this while existed_position is not invalidated. bool must_unsubscribe_mbox = !is_known_mbox_msg_pair( m_events, existed_position ); m_events.erase( existed_position ); if( must_unsubscribe_mbox ) { mbox->unsubscribe_event_handlers( msg_type, owner() ); } } }
void storage_t::drop_subscription_for_all_states( const mbox_t & mbox, const std::type_index & msg_type ) { const is_same_mbox_msg is_same{ mbox->id(), msg_type }; auto lower_bound = m_events.lower_bound( key_t{ mbox->id(), msg_type, nullptr } ); auto need_erase = [&] { return lower_bound != std::end(m_events) && is_same( lower_bound->first ); }; const bool events_found = need_erase(); if( events_found ) { do { m_events.erase( lower_bound++ ); } while( need_erase() ); // Note: since v.5.5.9 mbox unsubscription is initiated even if // it is MPSC mboxes. It is important for the case of message // delivery tracing. mbox->unsubscribe_event_handlers( msg_type, owner() ); } }
void storage_t::drop_subscription_for_all_states( const mbox_t & mbox_ref, const std::type_index & type_index ) { const key_t key( mbox_ref->id(), type_index ); auto it = m_map.lower_bound( key ); auto need_erase = [&] { return it != m_map.end() && key.is_same_mbox_msg_pair( it->first ); }; const bool found = need_erase(); if( found ) { do { m_hash_table.erase( &(it->first) ); m_map.erase( it++ ); } while( need_erase() ); mbox_ref->unsubscribe_event_handlers( type_index, owner() ); } }