From df63a78ad918daa96af99fa6bc0cfc9f25e06151 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 5 Dec 2024 13:07:27 +0100 Subject: [PATCH] WIP --- lib/base/io-engine.cpp | 73 +++++++++++++++++++++++++++++++++++++++--- lib/base/io-engine.hpp | 7 ++-- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/lib/base/io-engine.cpp b/lib/base/io-engine.cpp index 140ea2ecf..4c758d184 100644 --- a/lib/base/io-engine.cpp +++ b/lib/base/io-engine.cpp @@ -1,6 +1,7 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ #include "base/configuration.hpp" +#include "base/debug.hpp" #include "base/exception.hpp" #include "base/io-engine.hpp" #include "base/lazy-init.hpp" @@ -122,21 +123,83 @@ AsioConditionVariable::AsioConditionVariable(boost::asio::io_context& io) m_Timer.expires_at(boost::posix_time::pos_infin); } -void AsioConditionVariable::Wait(boost::asio::yield_context yc) +namespace icinga { - boost::system::error_code ec; - m_Timer.async_wait(yc[ec]); + +struct UnlockingYieldContext +{ + /*UnlockingYieldContext(boost::asio::yield_context yc, std::unique_lock* lock) + : YC(std::move(yc)), Lock(lock) + { + }*/ + + boost::asio::yield_context YC; + std::unique_lock* Lock; +}; + +template +class UnlockingYcHandler +{ +public: + UnlockingYcHandler(UnlockingYieldContext uyc) + : m_Handler(uyc.YC), m_Lock(uyc.Lock) + { + } + + template + auto operator()(Args&&... args) -> decltype(m_Handler(std::forward(args)...)) + { + m_Lock->unlock(); + return m_Handler(std::forward(args)...); + } + +private: + H m_Handler; + std::unique_lock* m_Lock; +}; + } -bool AsioConditionVariable::NotifyOne() +template +class boost::asio::async_result +{ +public: + using BaseType = async_result; + using completion_handler_type = UnlockingYcHandler; + using return_type = typename BaseType::return_type; + + template + explicit async_result(Args&&... args) : m_Result(std::forward(args)...) + { + } + + return_type get() + { + return m_Result.get(); + } + +private: + BaseType m_Result; +}; + +void AsioConditionVariable::Wait(std::unique_lock& lock, boost::asio::yield_context yc) +{ + VERIFY(lock); + boost::system::error_code ec; + m_Timer.async_wait(UnlockingYieldContext{yc[ec], &lock}); +} + +bool AsioConditionVariable::NotifyOne(std::mutex& mutex) { boost::system::error_code ec; + std::unique_lock lock (mutex); return m_Timer.cancel_one(ec); } -size_t AsioConditionVariable::NotifyAll() +size_t AsioConditionVariable::NotifyAll(std::mutex& mutex) { boost::system::error_code ec; + std::unique_lock lock (mutex); return m_Timer.cancel(ec); } diff --git a/lib/base/io-engine.hpp b/lib/base/io-engine.hpp index 0097f92d5..440497c91 100644 --- a/lib/base/io-engine.hpp +++ b/lib/base/io-engine.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -154,9 +155,9 @@ class AsioConditionVariable public: AsioConditionVariable(boost::asio::io_context& io); - void Wait(boost::asio::yield_context yc); - bool NotifyOne(); - size_t NotifyAll(); + void Wait(std::unique_lock& lock, boost::asio::yield_context yc); + bool NotifyOne(std::mutex& mutex); + size_t NotifyAll(std::mutex& mutex); private: boost::asio::deadline_timer m_Timer;