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() );
		}
	}