| 1769 | } |
| 1770 | |
| 1771 | void application_impl::invoke_handler(std::unique_lock<std::mutex>& _lock, std::shared_ptr<sync_handler>& _handler) { |
| 1772 | const std::thread::id its_id = std::this_thread::get_id(); |
| 1773 | |
| 1774 | auto its_sync_handler = |
| 1775 | std::make_shared<sync_handler>(_handler->service_id_, _handler->instance_id_, _handler->method_id_, _handler->session_id_, |
| 1776 | _handler->eventgroup_id_, _handler->client_id_, _handler->handler_type_); |
| 1777 | |
| 1778 | boost::asio::steady_timer its_dispatcher_timer(io_); |
| 1779 | its_dispatcher_timer.expires_after(std::chrono::milliseconds(max_dispatch_time_)); |
| 1780 | its_dispatcher_timer.async_wait([this, its_sync_handler](const boost::system::error_code& _error) { |
| 1781 | if (!_error) { |
| 1782 | print_blocking_call(its_sync_handler); |
| 1783 | std::scoped_lock its_lock{handlers_mutex_}; |
| 1784 | if (has_active_dispatcher()) { |
| 1785 | dispatcher_condition_.notify_all(); |
| 1786 | } else { |
| 1787 | // If possible, create a new dispatcher thread to unblock. |
| 1788 | // If this is _not_ possible, dispatching is blocked until |
| 1789 | // at least one of the active handler calls returns. |
| 1790 | if (dispatchers_.size() < max_dispatchers_) { |
| 1791 | if (is_dispatching_) { |
| 1792 | auto its_dispatcher = std::make_shared<std::thread>([self = shared_from_this()]() { self->dispatch(); }); |
| 1793 | dispatchers_[its_dispatcher->get_id()] = its_dispatcher; |
| 1794 | } else { |
| 1795 | VSOMEIP_INFO << "Won't start new dispatcher thread as Client=" << hex4(get_client()) << " is shutting down"; |
| 1796 | } |
| 1797 | } else { |
| 1798 | VSOMEIP_ERROR << "Maximum number of dispatchers exceeded. Configuration: Max dispatchers: " << max_dispatchers_ |
| 1799 | << " Max dispatch time: " << max_dispatch_time_; |
| 1800 | } |
| 1801 | } |
| 1802 | } |
| 1803 | }); |
| 1804 | if (client_side_logging_ |
| 1805 | && (client_side_logging_filter_.empty() |
| 1806 | || (1 == client_side_logging_filter_.count(std::make_tuple(its_sync_handler->service_id_, ANY_INSTANCE))) |
| 1807 | || (1 == client_side_logging_filter_.count(std::make_tuple(its_sync_handler->service_id_, its_sync_handler->instance_id_))))) { |
| 1808 | VSOMEIP_INFO << "Invoking handler: (" << hex4(client_) << "): [" << hex4(its_sync_handler->service_id_) << "." |
| 1809 | << hex4(its_sync_handler->instance_id_) << "." << hex4(its_sync_handler->method_id_) << ":" |
| 1810 | << hex4(its_sync_handler->session_id_) << "] " |
| 1811 | << "type=" << static_cast<std::uint32_t>(its_sync_handler->handler_type_) << " thread=" << std::hex << its_id; |
| 1812 | } |
| 1813 | |
| 1814 | running_dispatchers_.insert(its_id); |
| 1815 | |
| 1816 | if (is_dispatching_) { |
| 1817 | _lock.unlock(); |
| 1818 | try { |
| 1819 | _handler->handler_(); |
| 1820 | } catch (const std::exception& e) { |
| 1821 | VSOMEIP_ERROR_P << "Caught exception: " << e.what(); |
| 1822 | print_blocking_call(its_sync_handler); |
| 1823 | } |
| 1824 | _lock.lock(); |
| 1825 | } |
| 1826 | |
| 1827 | its_dispatcher_timer.cancel(); |
| 1828 | running_dispatchers_.erase(its_id); |
nothing calls this directly
no test coverage detected