Open KuDeSnik33ra opened 1 year ago
I've read the https://www.boost.org/doc/libs/develop/doc/html/boost_asio/std_executors.html After adding
namespace asio {
namespace traits {
#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
template <typename F>
struct execute_member<minimal_io_executor, F>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef void result_type;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
template <>
struct equality_comparable<minimal_io_executor>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
template <>
struct query_member<minimal_io_executor,
asio::execution::context_t>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef asio::execution_context& result_type;
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
template <typename Property>
struct query_static_constexpr_member<minimal_io_executor, Property,
typename enable_if<
std::is_convertible<Property, asio::execution::blocking_t>::value
>::type>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef asio::execution::blocking_t::never_t result_type;
static constexpr result_type value() noexcept { return result_type(); }
};
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
} // namespace traits
}
to the minimal_io_executor way compiled successfully
Now the question is: Is this proper non-deprecated way to create custom executor? Is there another way to do it?
And another question: Is it the same - to create socket passing io_context, and to create socket passing io_context->get_executor()?
Added
minimal_io_executor(minimal_io_executor&& other) : context_(other.context_)
{
other.hEvent = NULL;
}
error C2679: binary '=': no operator found which takes a right-hand operand of type 'minimal_io_executor' (or there is no acceptable conversion)
So, the executor can not own any data - only store references/pointers to data, created elsewhere.
How can I store the 'f' argument to a queue? What type should I use for the queue?
template <class F>
void execute(F f) const
{
}
Here is the soultion, which seems to be working (maybe somebody will need it too). Does anybody have any suggestions?
#include <functional>
#include <asio.hpp>
class AsioFuncWrapperBase
{
public:
virtual void execute() = 0;
virtual ~AsioFuncWrapperBase() = default;
};
template <class F>
class AsioFuncWrapper : public AsioFuncWrapperBase
{
public:
AsioFuncWrapper(F f) : m_f(ASIO_MOVE_CAST(F)(f)) {};
virtual void execute() override { m_f(); };
private:
F m_f;
};
using AsioFuncWrapperBasePtr = std::shared_ptr<AsioFuncWrapperBase>;
using AsioWinRemoteExecutorPushFuncType = std::function<void(const AsioFuncWrapperBasePtr& func)>;
struct AsioWinRemoteExecutor
{
asio::execution_context* context_;
AsioWinRemoteExecutorPushFuncType& pushFuncProc;
bool operator==(const AsioWinRemoteExecutor& other) const noexcept
{
return context_ == other.context_;
}
bool operator!=(const AsioWinRemoteExecutor& other) const noexcept
{
return !(*this == other);
}
asio::execution_context& query(
asio::execution::context_t) const noexcept
{
return *context_;
}
static constexpr asio::execution::blocking_t::never_t query(
asio::execution::blocking_t) noexcept
{
// This executor always has blocking.never semantics.
return asio::execution::blocking.never;
}
template <class F>
void execute(F f) const
{
if (pushFuncProc)
{
pushFuncProc(AsioFuncWrapperBasePtr(new AsioFuncWrapper(ASIO_MOVE_CAST(F)(f))));
}
}
};
namespace asio {
namespace traits {
#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
template <typename F>
struct execute_member<AsioWinRemoteExecutor, F>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef void result_type;
};
#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
template <>
struct equality_comparable<AsioWinRemoteExecutor>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
};
#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
template <>
struct query_member<AsioWinRemoteExecutor,
execution::context_t>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef execution_context& result_type;
};
#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
template <typename Property>
struct query_static_constexpr_member<AsioWinRemoteExecutor, Property,
typename enable_if<
std::is_convertible<Property, execution::blocking_t>::value
>::type>
{
static constexpr bool is_valid = true;
static constexpr bool is_noexcept = true;
typedef execution::blocking_t::never_t result_type;
static constexpr result_type value() noexcept { return result_type(); }
};
#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
} // namespace traits
} // namespace asio
Is it possible - in latest versions of asio - to create io_context with custom executor? I was trying to do it in many way, like:
error C2440: 'initializing': cannot convert from 'initializer list' to 'asio::io_context'
and this way:
error C2672: 'asio::post': no matching overloaded function found
Can anyone, please, help me to understand - what I am doing wrong? And where is the documentation about that?
My overall task is to run io_context on windows(IOCP) on separate thread, but call the completition callbacks in the main MsgCycle thread - so in the iocp thread I have to push callback to a queue and call SetEvent() for MsgCycle's MsgWaitForMultipleObjects().
I need this because the app is using Lua scripts, which can be called only in one thread, so suggestions not to do it at all are not relevant.