void actor_t::on_message(int fd, const message_t& message) { auto it = m_channels.find(fd); if(it == m_channels.end()) { return; } m_dispatch->invoke(message, std::make_shared<upstream_t>( it->second, message.band() )); }
void session_t::invoke(const message_t& message) { channel_map_t::const_iterator lb, ub; channel_map_t::key_type index = message.band(); std::shared_ptr<channel_t> channel; { auto locked = channels.synchronize(); std::tie(lb, ub) = locked->equal_range(index); if(lb == ub) { if(!prototype || index <= max_channel) { return; } // NOTE: Checking whether channel number is always higher than the previous channel number // is similar to an infinite TIME_WAIT timeout for TCP sockets. It might be not the best // aproach, but since we have 2^64 possible channels, unlike 2^16 ports for sockets, it is // fit to avoid stray messages. max_channel = index; std::tie(lb, std::ignore) = locked->insert({index, std::make_shared<channel_t>( prototype, std::make_shared<basic_upstream_t>(shared_from_this(), index) )}); } // NOTE: The virtual channel pointer is copied here so that if the slot decides to close the // virtual channel, it won't destroy it inside the channel_t::invoke(). Instead, it will be // destroyed when this function scope is exited, liberating us from thinking of some voodoo // magic to handle it. channel = lb->second; } channel->invoke(message); }
void session_t::invoke(const message_t& message) { channel_map_t::const_iterator lb, ub; channel_map_t::key_type index = message.band(); std::shared_ptr<channel_t> channel; { auto locked = channels.synchronize(); std::tie(lb, ub) = locked->equal_range(index); if(lb == ub) { if(!prototype || index <= max_channel) { return; } max_channel = index; auto upstream = std::make_shared<upstream_t>(shared_from_this(), index); upstream->auto_revoke(); std::tie(lb, std::ignore) = locked->insert({ index, std::make_shared<channel_t>(prototype, upstream) }); } // NOTE: The virtual channel pointer is copied here so that if the slot decides to close the // virtual channel, it won't destroy it inside the channel_t::invoke(). Instead, it will be // destroyed when this function scope is exited, liberating us from thinking of some voodoo // magic to handle it. channel = lb->second; } channel->invoke(message); }