update boost
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// detail/array.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/array_fwd.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/assert.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/atomic_count.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -32,12 +32,34 @@ namespace detail {
|
||||
#if !defined(BOOST_ASIO_HAS_THREADS)
|
||||
typedef long atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { a += b; }
|
||||
inline void decrement(atomic_count& a, long b) { a -= b; }
|
||||
inline void ref_count_up(atomic_count& a) { ++a; }
|
||||
inline bool ref_count_down(atomic_count& a) { return --a == 0; }
|
||||
#elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
typedef std::atomic<long> atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { a += b; }
|
||||
inline void decrement(atomic_count& a, long b) { a -= b; }
|
||||
|
||||
inline void ref_count_up(atomic_count& a)
|
||||
{
|
||||
a.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline bool ref_count_down(atomic_count& a)
|
||||
{
|
||||
if (a.fetch_sub(1, std::memory_order_release) == 1)
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else // defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
typedef boost::detail::atomic_count atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; }
|
||||
inline void decrement(atomic_count& a, long b) { while (b > 0) --a, --b; }
|
||||
inline void ref_count_up(atomic_count& a) { ++a; }
|
||||
inline bool ref_count_down(atomic_count& a) { return --a == 0; }
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// detail/base_from_cancellation_state.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
|
||||
#define BOOST_ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/associated_cancellation_slot.hpp>
|
||||
#include <boost/asio/cancellation_state.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler, typename = void>
|
||||
class base_from_cancellation_state
|
||||
{
|
||||
public:
|
||||
typedef cancellation_slot cancellation_slot_type;
|
||||
|
||||
cancellation_slot_type get_cancellation_slot() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_state_.slot();
|
||||
}
|
||||
|
||||
cancellation_state get_cancellation_state() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_state_;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit base_from_cancellation_state(const Handler& handler)
|
||||
: cancellation_state_(
|
||||
boost::asio::get_associated_cancellation_slot(handler))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
base_from_cancellation_state(const Handler& handler, Filter filter)
|
||||
: cancellation_state_(
|
||||
boost::asio::get_associated_cancellation_slot(handler), filter, filter)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InFilter, typename OutFilter>
|
||||
base_from_cancellation_state(const Handler& handler,
|
||||
BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
|
||||
BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
|
||||
: cancellation_state_(
|
||||
boost::asio::get_associated_cancellation_slot(handler),
|
||||
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
|
||||
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter))
|
||||
{
|
||||
}
|
||||
|
||||
void reset_cancellation_state(const Handler& handler)
|
||||
{
|
||||
cancellation_state_ = cancellation_state(
|
||||
boost::asio::get_associated_cancellation_slot(handler));
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
void reset_cancellation_state(const Handler& handler, Filter filter)
|
||||
{
|
||||
cancellation_state_ = cancellation_state(
|
||||
boost::asio::get_associated_cancellation_slot(handler), filter, filter);
|
||||
}
|
||||
|
||||
template <typename InFilter, typename OutFilter>
|
||||
void reset_cancellation_state(const Handler& handler,
|
||||
BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
|
||||
BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
|
||||
{
|
||||
cancellation_state_ = cancellation_state(
|
||||
boost::asio::get_associated_cancellation_slot(handler),
|
||||
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
|
||||
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter));
|
||||
}
|
||||
|
||||
cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_state_.cancelled();
|
||||
}
|
||||
|
||||
private:
|
||||
cancellation_state cancellation_state_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
class base_from_cancellation_state<Handler,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
typename associated_cancellation_slot<
|
||||
Handler, cancellation_slot
|
||||
>::asio_associated_cancellation_slot_is_unspecialised,
|
||||
void
|
||||
>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
cancellation_state get_cancellation_state() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_state();
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit base_from_cancellation_state(const Handler&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
base_from_cancellation_state(const Handler&, Filter)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InFilter, typename OutFilter>
|
||||
base_from_cancellation_state(const Handler&,
|
||||
BOOST_ASIO_MOVE_ARG(InFilter),
|
||||
BOOST_ASIO_MOVE_ARG(OutFilter))
|
||||
{
|
||||
}
|
||||
|
||||
void reset_cancellation_state(const Handler&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
void reset_cancellation_state(const Handler&, Filter)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InFilter, typename OutFilter>
|
||||
void reset_cancellation_state(const Handler&,
|
||||
BOOST_ASIO_MOVE_ARG(InFilter),
|
||||
BOOST_ASIO_MOVE_ARG(OutFilter))
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_ASIO_CONSTEXPR cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_type::none;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/base_from_completion_cond.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/bind_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -16,8 +16,7 @@
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/associator.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
@@ -29,6 +28,113 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
class binder0
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
binder0(int, BOOST_ASIO_MOVE_ARG(T) handler)
|
||||
: handler_(BOOST_ASIO_MOVE_CAST(T)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
binder0(Handler& handler)
|
||||
: handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
binder0(const binder0& other)
|
||||
: handler_(other.handler_)
|
||||
{
|
||||
}
|
||||
|
||||
binder0(binder0&& other)
|
||||
: handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
void operator()()
|
||||
{
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)();
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
handler_();
|
||||
}
|
||||
|
||||
//private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder0<Handler>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder0<Handler>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
inline bool asio_handler_is_continuation(
|
||||
binder0<Handler>* this_handler)
|
||||
{
|
||||
return boost_asio_handler_cont_helpers::is_continuation(
|
||||
this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder0<Handler>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder0<Handler>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
inline binder0<typename decay<Handler>::type> bind_handler(
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
{
|
||||
return binder0<typename decay<Handler>::type>(
|
||||
0, BOOST_ASIO_MOVE_CAST(Handler)(handler));
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
class binder1
|
||||
{
|
||||
@@ -62,7 +168,8 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_));
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_));
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
@@ -76,19 +183,29 @@ public:
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
@@ -100,19 +217,27 @@ inline bool asio_handler_is_continuation(
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
@@ -161,7 +286,8 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_));
|
||||
}
|
||||
|
||||
@@ -177,19 +303,29 @@ public:
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
@@ -201,19 +337,27 @@ inline bool asio_handler_is_continuation(
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
@@ -267,8 +411,10 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_),
|
||||
static_cast<const Arg3&>(arg3_));
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
@@ -284,19 +430,29 @@ public:
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
|
||||
@@ -309,20 +465,28 @@ inline bool asio_handler_is_continuation(
|
||||
|
||||
template <typename Function, typename Handler,
|
||||
typename Arg1, typename Arg2, typename Arg3>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler,
|
||||
typename Arg1, typename Arg2, typename Arg3>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
|
||||
@@ -382,8 +546,10 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_),
|
||||
static_cast<const Arg3&>(arg3_),
|
||||
static_cast<const Arg4&>(arg4_));
|
||||
}
|
||||
|
||||
@@ -402,20 +568,30 @@ public:
|
||||
|
||||
template <typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1,
|
||||
@@ -429,20 +605,28 @@ inline bool asio_handler_is_continuation(
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1,
|
||||
@@ -507,9 +691,12 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
|
||||
static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_),
|
||||
static_cast<const Arg2&>(arg2_),
|
||||
static_cast<const Arg3&>(arg3_),
|
||||
static_cast<const Arg4&>(arg4_),
|
||||
static_cast<const Arg5&>(arg5_));
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
@@ -528,20 +715,30 @@ public:
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2,
|
||||
typename Arg3, typename Arg4, typename Arg5>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2,
|
||||
typename Arg3, typename Arg4, typename Arg5>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2,
|
||||
@@ -555,20 +752,28 @@ inline bool asio_handler_is_continuation(
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4, typename Arg5>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(Function& function,
|
||||
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1,
|
||||
typename Arg2, typename Arg3, typename Arg4, typename Arg5>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(const Function& function,
|
||||
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2,
|
||||
@@ -602,7 +807,8 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(BOOST_ASIO_MOVE_CAST(Arg1)(arg1_));
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
BOOST_ASIO_MOVE_CAST(Arg1)(arg1_));
|
||||
}
|
||||
|
||||
//private:
|
||||
@@ -611,19 +817,29 @@ public:
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
@@ -635,11 +851,15 @@ inline bool asio_handler_is_continuation(
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1>
|
||||
inline void asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
@@ -663,7 +883,8 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
|
||||
static_cast<const Arg1&>(arg1_),
|
||||
BOOST_ASIO_MOVE_CAST(Arg2)(arg2_));
|
||||
}
|
||||
|
||||
@@ -674,19 +895,29 @@ public:
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
inline asio_handler_allocate_is_deprecated
|
||||
asio_handler_allocate(std::size_t size,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
|
||||
return asio_handler_allocate_is_no_longer_used();
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return boost_asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
inline asio_handler_deallocate_is_deprecated
|
||||
asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_deallocate_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
@@ -698,113 +929,211 @@ inline bool asio_handler_is_continuation(
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
inline asio_handler_invoke_is_deprecated
|
||||
asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
return asio_handler_invoke_is_no_longer_used();
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Handler, typename Arg1, typename Allocator>
|
||||
struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder0<Handler>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::binder1<Handler, Arg1>& h,
|
||||
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder0<Handler>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder0<Handler>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
|
||||
struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder1<Handler, Arg1>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::binder2<Handler, Arg1, Arg2>& h,
|
||||
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder1<Handler, Arg1>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder1<Handler, Arg1>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Executor>
|
||||
struct associated_executor<detail::binder1<Handler, Arg1>, Executor>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename Arg2,
|
||||
typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder2<Handler, Arg1, Arg2>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::binder1<Handler, Arg1>& h,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder2<Handler, Arg1, Arg2>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder2<Handler, Arg1, Arg2>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Executor>
|
||||
struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder3<Handler, Arg1, Arg2, Arg3>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::binder2<Handler, Arg1, Arg2>& h,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Handler, typename Arg1, typename Allocator>
|
||||
struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::move_binder1<Handler, Arg1>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::move_binder1<Handler, Arg1>& h,
|
||||
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::move_binder1<Handler, Arg1>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::move_binder1<Handler, Arg1>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
|
||||
struct associated_allocator<
|
||||
detail::move_binder2<Handler, Arg1, Arg2>, Allocator>
|
||||
template <template <typename, typename> class Associator,
|
||||
typename Handler, typename Arg1, typename Arg2,
|
||||
typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
detail::move_binder2<Handler, Arg1, Arg2>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
|
||||
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
|
||||
static typename Associator<Handler, DefaultCandidate>::type
|
||||
get(const detail::move_binder2<Handler, Arg1, Arg2>& h) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Executor>
|
||||
struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::move_binder1<Handler, Arg1>& h,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
|
||||
typename Associator<Handler, DefaultCandidate>::type)
|
||||
get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
|
||||
const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
|
||||
BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
|
||||
Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Executor>
|
||||
struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
110
linx64/include/boost/asio/detail/blocking_executor_op.hpp
Normal file
110
linx64/include/boost/asio/detail/blocking_executor_op.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// detail/blocking_executor_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_BLOCKING_EXECUTOR_OP_HPP
|
||||
#define BOOST_ASIO_DETAIL_BLOCKING_EXECUTOR_OP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/event.hpp>
|
||||
#include <boost/asio/detail/fenced_block.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/mutex.hpp>
|
||||
#include <boost/asio/detail/scheduler_operation.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Operation = scheduler_operation>
|
||||
class blocking_executor_op_base : public Operation
|
||||
{
|
||||
public:
|
||||
blocking_executor_op_base(typename Operation::func_type complete_func)
|
||||
: Operation(complete_func),
|
||||
is_complete_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
while (!is_complete_)
|
||||
event_.wait(lock);
|
||||
}
|
||||
|
||||
protected:
|
||||
struct do_complete_cleanup
|
||||
{
|
||||
~do_complete_cleanup()
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(op_->mutex_);
|
||||
op_->is_complete_ = true;
|
||||
op_->event_.unlock_and_signal_one_for_destruction(lock);
|
||||
}
|
||||
|
||||
blocking_executor_op_base* op_;
|
||||
};
|
||||
|
||||
private:
|
||||
boost::asio::detail::mutex mutex_;
|
||||
boost::asio::detail::event event_;
|
||||
bool is_complete_;
|
||||
};
|
||||
|
||||
template <typename Handler, typename Operation = scheduler_operation>
|
||||
class blocking_executor_op : public blocking_executor_op_base<Operation>
|
||||
{
|
||||
public:
|
||||
blocking_executor_op(Handler& h)
|
||||
: blocking_executor_op_base<Operation>(&blocking_executor_op::do_complete),
|
||||
handler_(h)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, Operation* base,
|
||||
const boost::system::error_code& /*ec*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
blocking_executor_op* o(static_cast<blocking_executor_op*>(base));
|
||||
|
||||
typename blocking_executor_op_base<Operation>::do_complete_cleanup
|
||||
on_exit = { o };
|
||||
(void)on_exit;
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
fenced_block b(fenced_block::half);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_BEGIN(());
|
||||
boost_asio_handler_invoke_helpers::invoke(o->handler_, o->handler_);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_END;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Handler& handler_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_BLOCKING_EXECUTOR_OP_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/buffer_resize_guard.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/buffer_sequence_adapter.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/detail/array_fwd.hpp>
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
#include <boost/asio/registered_buffer.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -105,6 +106,9 @@ class buffer_sequence_adapter
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = false };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
|
||||
: count_(0), total_buffer_size_(0)
|
||||
{
|
||||
@@ -128,6 +132,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -154,6 +163,16 @@ public:
|
||||
boost::asio::buffer_sequence_end(buffer_sequence));
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 8192 };
|
||||
|
||||
static Buffer linearise(const Buffers& buffer_sequence,
|
||||
const boost::asio::mutable_buffer& storage)
|
||||
{
|
||||
return buffer_sequence_adapter::linearise(
|
||||
boost::asio::buffer_sequence_begin(buffer_sequence),
|
||||
boost::asio::buffer_sequence_end(buffer_sequence), storage);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Iterator>
|
||||
void init(Iterator begin, Iterator end)
|
||||
@@ -202,6 +221,30 @@ private:
|
||||
return Buffer();
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static Buffer linearise(Iterator begin, Iterator end,
|
||||
const boost::asio::mutable_buffer& storage)
|
||||
{
|
||||
boost::asio::mutable_buffer unused_storage = storage;
|
||||
Iterator iter = begin;
|
||||
while (iter != end && unused_storage.size() != 0)
|
||||
{
|
||||
Buffer buffer(*iter);
|
||||
++iter;
|
||||
if (buffer.size() == 0)
|
||||
continue;
|
||||
if (unused_storage.size() == storage.size())
|
||||
{
|
||||
if (iter == end)
|
||||
return buffer;
|
||||
if (buffer.size() >= unused_storage.size())
|
||||
return buffer;
|
||||
}
|
||||
unused_storage += boost::asio::buffer_copy(unused_storage, buffer);
|
||||
}
|
||||
return Buffer(storage.data(), storage.size() - unused_storage.size());
|
||||
}
|
||||
|
||||
native_buffer_type buffers_[max_buffers];
|
||||
std::size_t count_;
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -212,6 +255,9 @@ class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffer>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::mutable_buffer& buffer_sequence)
|
||||
{
|
||||
@@ -234,6 +280,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -254,6 +305,14 @@ public:
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(const boost::asio::mutable_buffer& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -264,6 +323,9 @@ class buffer_sequence_adapter<Buffer, boost::asio::const_buffer>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::const_buffer& buffer_sequence)
|
||||
{
|
||||
@@ -286,6 +348,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -306,6 +373,14 @@ public:
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(const boost::asio::const_buffer& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -318,6 +393,9 @@ class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::mutable_buffers_1& buffer_sequence)
|
||||
{
|
||||
@@ -340,6 +418,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -360,6 +443,14 @@ public:
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(const boost::asio::mutable_buffers_1& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -370,6 +461,9 @@ class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::const_buffers_1& buffer_sequence)
|
||||
{
|
||||
@@ -392,6 +486,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -412,6 +511,14 @@ public:
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(const boost::asio::const_buffers_1& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence);
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -419,11 +526,162 @@ private:
|
||||
|
||||
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Buffer>
|
||||
class buffer_sequence_adapter<Buffer, boost::asio::mutable_registered_buffer>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = true };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::mutable_registered_buffer& buffer_sequence)
|
||||
{
|
||||
init_native_buffer(buffer_, buffer_sequence.buffer());
|
||||
total_buffer_size_ = buffer_sequence.size();
|
||||
registered_id_ = buffer_sequence.id();
|
||||
}
|
||||
|
||||
native_buffer_type* buffers()
|
||||
{
|
||||
return &buffer_;
|
||||
}
|
||||
|
||||
std::size_t count() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::size_t total_size() const
|
||||
{
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_id_;
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
}
|
||||
|
||||
static bool all_empty(
|
||||
const boost::asio::mutable_registered_buffer& buffer_sequence)
|
||||
{
|
||||
return buffer_sequence.size() == 0;
|
||||
}
|
||||
|
||||
static void validate(
|
||||
const boost::asio::mutable_registered_buffer& buffer_sequence)
|
||||
{
|
||||
buffer_sequence.data();
|
||||
}
|
||||
|
||||
static Buffer first(
|
||||
const boost::asio::mutable_registered_buffer& buffer_sequence)
|
||||
{
|
||||
return Buffer(buffer_sequence.buffer());
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(
|
||||
const boost::asio::mutable_registered_buffer& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence.buffer());
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
registered_buffer_id registered_id_;
|
||||
};
|
||||
|
||||
template <typename Buffer>
|
||||
class buffer_sequence_adapter<Buffer, boost::asio::const_registered_buffer>
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = true };
|
||||
enum { is_registered_buffer = true };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::asio::const_registered_buffer& buffer_sequence)
|
||||
{
|
||||
init_native_buffer(buffer_, buffer_sequence.buffer());
|
||||
total_buffer_size_ = buffer_sequence.size();
|
||||
registered_id_ = buffer_sequence.id();
|
||||
}
|
||||
|
||||
native_buffer_type* buffers()
|
||||
{
|
||||
return &buffer_;
|
||||
}
|
||||
|
||||
std::size_t count() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::size_t total_size() const
|
||||
{
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_id_;
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
}
|
||||
|
||||
static bool all_empty(
|
||||
const boost::asio::const_registered_buffer& buffer_sequence)
|
||||
{
|
||||
return buffer_sequence.size() == 0;
|
||||
}
|
||||
|
||||
static void validate(
|
||||
const boost::asio::const_registered_buffer& buffer_sequence)
|
||||
{
|
||||
buffer_sequence.data();
|
||||
}
|
||||
|
||||
static Buffer first(
|
||||
const boost::asio::const_registered_buffer& buffer_sequence)
|
||||
{
|
||||
return Buffer(buffer_sequence.buffer());
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 1 };
|
||||
|
||||
static Buffer linearise(
|
||||
const boost::asio::const_registered_buffer& buffer_sequence,
|
||||
const Buffer&)
|
||||
{
|
||||
return Buffer(buffer_sequence.buffer());
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffer_;
|
||||
std::size_t total_buffer_size_;
|
||||
registered_buffer_id registered_id_;
|
||||
};
|
||||
|
||||
template <typename Buffer, typename Elem>
|
||||
class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = false };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const boost::array<Elem, 2>& buffer_sequence)
|
||||
{
|
||||
@@ -447,6 +705,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -469,6 +732,19 @@ public:
|
||||
? buffer_sequence[0] : buffer_sequence[1]);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 8192 };
|
||||
|
||||
static Buffer linearise(const boost::array<Elem, 2>& buffer_sequence,
|
||||
const boost::asio::mutable_buffer& storage)
|
||||
{
|
||||
if (buffer_sequence[0].size() == 0)
|
||||
return Buffer(buffer_sequence[1]);
|
||||
if (buffer_sequence[1].size() == 0)
|
||||
return Buffer(buffer_sequence[0]);
|
||||
return Buffer(storage.data(),
|
||||
boost::asio::buffer_copy(storage, buffer_sequence));
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffers_[2];
|
||||
std::size_t total_buffer_size_;
|
||||
@@ -481,6 +757,9 @@ class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
|
||||
: buffer_sequence_adapter_base
|
||||
{
|
||||
public:
|
||||
enum { is_single_buffer = false };
|
||||
enum { is_registered_buffer = false };
|
||||
|
||||
explicit buffer_sequence_adapter(
|
||||
const std::array<Elem, 2>& buffer_sequence)
|
||||
{
|
||||
@@ -504,6 +783,11 @@ public:
|
||||
return total_buffer_size_;
|
||||
}
|
||||
|
||||
registered_buffer_id registered_id() const
|
||||
{
|
||||
return registered_buffer_id();
|
||||
}
|
||||
|
||||
bool all_empty() const
|
||||
{
|
||||
return total_buffer_size_ == 0;
|
||||
@@ -526,6 +810,19 @@ public:
|
||||
? buffer_sequence[0] : buffer_sequence[1]);
|
||||
}
|
||||
|
||||
enum { linearisation_storage_size = 8192 };
|
||||
|
||||
static Buffer linearise(const std::array<Elem, 2>& buffer_sequence,
|
||||
const boost::asio::mutable_buffer& storage)
|
||||
{
|
||||
if (buffer_sequence[0].size() == 0)
|
||||
return Buffer(buffer_sequence[1]);
|
||||
if (buffer_sequence[1].size() == 0)
|
||||
return Buffer(buffer_sequence[0]);
|
||||
return Buffer(storage.data(),
|
||||
boost::asio::buffer_copy(storage, buffer_sequence));
|
||||
}
|
||||
|
||||
private:
|
||||
native_buffer_type buffers_[2];
|
||||
std::size_t total_buffer_size_;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/buffered_stream_storage.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
91
linx64/include/boost/asio/detail/bulk_executor_op.hpp
Normal file
91
linx64/include/boost/asio/detail/bulk_executor_op.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// detail/bulk_executor_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_BULK_EXECUTOR_OP_HPP
|
||||
#define BOOST_ASIO_DETAIL_BULK_EXECUTOR_OP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
#include <boost/asio/detail/fenced_block.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/scheduler_operation.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler, typename Alloc,
|
||||
typename Operation = scheduler_operation>
|
||||
class bulk_executor_op : public Operation
|
||||
{
|
||||
public:
|
||||
BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(bulk_executor_op);
|
||||
|
||||
template <typename H>
|
||||
bulk_executor_op(BOOST_ASIO_MOVE_ARG(H) h,
|
||||
const Alloc& allocator, std::size_t i)
|
||||
: Operation(&bulk_executor_op::do_complete),
|
||||
handler_(BOOST_ASIO_MOVE_CAST(H)(h)),
|
||||
allocator_(allocator),
|
||||
index_(i)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, Operation* base,
|
||||
const boost::system::error_code& /*ec*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
bulk_executor_op* o(static_cast<bulk_executor_op*>(base));
|
||||
Alloc allocator(o->allocator_);
|
||||
ptr p = { detail::addressof(allocator), o, o };
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder1<Handler, std::size_t> handler(o->handler_, o->index_);
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
fenced_block b(fenced_block::half);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_BEGIN(());
|
||||
boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_END;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
Alloc allocator_;
|
||||
std::size_t index_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_BULK_EXECUTOR_OP_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/call_stack.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/chrono.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/chrono_time_traits.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/completion_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -28,17 +28,17 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class completion_handler : public operation
|
||||
{
|
||||
public:
|
||||
BOOST_ASIO_DEFINE_HANDLER_PTR(completion_handler);
|
||||
|
||||
completion_handler(Handler& h)
|
||||
completion_handler(Handler& h, const IoExecutor& io_ex)
|
||||
: operation(&completion_handler::do_complete),
|
||||
handler_(BOOST_ASIO_MOVE_CAST(Handler)(h))
|
||||
handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)),
|
||||
work_(handler_, io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@@ -48,10 +48,14 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
completion_handler* h(static_cast<completion_handler*>(base));
|
||||
ptr p = { boost::asio::detail::addressof(h->handler_), h, h };
|
||||
handler_work<Handler> w(h->handler_);
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*h));
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
handler_work<Handler, IoExecutor> w(
|
||||
BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
|
||||
h->work_));
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
@@ -74,6 +78,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
handler_work<Handler, IoExecutor> work_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
330
linx64/include/boost/asio/detail/composed_work.hpp
Normal file
330
linx64/include/boost/asio/detail/composed_work.hpp
Normal file
@@ -0,0 +1,330 @@
|
||||
//
|
||||
// detail/composed_work.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_COMPOSED_WORK_HPP
|
||||
#define BOOST_ASIO_DETAIL_COMPOSED_WORK_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
#include <boost/asio/detail/variadic_templates.hpp>
|
||||
#include <boost/asio/execution/executor.hpp>
|
||||
#include <boost/asio/execution/outstanding_work.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/is_executor.hpp>
|
||||
#include <boost/asio/system_executor.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Executor, typename = void>
|
||||
class composed_work_guard
|
||||
{
|
||||
public:
|
||||
typedef typename decay<
|
||||
typename prefer_result<Executor,
|
||||
execution::outstanding_work_t::tracked_t
|
||||
>::type
|
||||
>::type executor_type;
|
||||
|
||||
composed_work_guard(const Executor& ex)
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
}
|
||||
|
||||
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_;
|
||||
}
|
||||
|
||||
private:
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct composed_work_guard<system_executor>
|
||||
{
|
||||
public:
|
||||
typedef system_executor executor_type;
|
||||
|
||||
composed_work_guard(const system_executor&)
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
}
|
||||
|
||||
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return system_executor();
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
|
||||
|
||||
template <typename Executor>
|
||||
struct composed_work_guard<Executor,
|
||||
typename enable_if<
|
||||
!execution::is_executor<Executor>::value
|
||||
>::type> : executor_work_guard<Executor>
|
||||
{
|
||||
composed_work_guard(const Executor& ex)
|
||||
: executor_work_guard<Executor>(ex)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
|
||||
|
||||
template <typename>
|
||||
struct composed_io_executors;
|
||||
|
||||
template <>
|
||||
struct composed_io_executors<void()>
|
||||
{
|
||||
composed_io_executors() BOOST_ASIO_NOEXCEPT
|
||||
: head_(system_executor())
|
||||
{
|
||||
}
|
||||
|
||||
typedef system_executor head_type;
|
||||
system_executor head_;
|
||||
};
|
||||
|
||||
inline composed_io_executors<void()> make_composed_io_executors()
|
||||
{
|
||||
return composed_io_executors<void()>();
|
||||
}
|
||||
|
||||
template <typename Head>
|
||||
struct composed_io_executors<void(Head)>
|
||||
{
|
||||
explicit composed_io_executors(const Head& ex) BOOST_ASIO_NOEXCEPT
|
||||
: head_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
typedef Head head_type;
|
||||
Head head_;
|
||||
};
|
||||
|
||||
template <typename Head>
|
||||
inline composed_io_executors<void(Head)>
|
||||
make_composed_io_executors(const Head& head)
|
||||
{
|
||||
return composed_io_executors<void(Head)>(head);
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
struct composed_io_executors<void(Head, Tail...)>
|
||||
{
|
||||
explicit composed_io_executors(const Head& head,
|
||||
const Tail&... tail) BOOST_ASIO_NOEXCEPT
|
||||
: head_(head),
|
||||
tail_(tail...)
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
head_.reset();
|
||||
tail_.reset();
|
||||
}
|
||||
|
||||
typedef Head head_type;
|
||||
Head head_;
|
||||
composed_io_executors<void(Tail...)> tail_;
|
||||
};
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
inline composed_io_executors<void(Head, Tail...)>
|
||||
make_composed_io_executors(const Head& head, const Tail&... tail)
|
||||
{
|
||||
return composed_io_executors<void(Head, Tail...)>(head, tail...);
|
||||
}
|
||||
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \
|
||||
template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
|
||||
struct composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
|
||||
{ \
|
||||
explicit composed_io_executors(const Head& head, \
|
||||
BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
|
||||
: head_(head), \
|
||||
tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
void reset() \
|
||||
{ \
|
||||
head_.reset(); \
|
||||
tail_.reset(); \
|
||||
} \
|
||||
\
|
||||
typedef Head head_type; \
|
||||
Head head_; \
|
||||
composed_io_executors<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
|
||||
}; \
|
||||
\
|
||||
template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
|
||||
inline composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
|
||||
make_composed_io_executors(const Head& head, \
|
||||
BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
|
||||
{ \
|
||||
return composed_io_executors< \
|
||||
void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
|
||||
head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
|
||||
} \
|
||||
/**/
|
||||
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)
|
||||
#undef BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename>
|
||||
struct composed_work;
|
||||
|
||||
template <>
|
||||
struct composed_work<void()>
|
||||
{
|
||||
typedef composed_io_executors<void()> executors_type;
|
||||
|
||||
composed_work(const executors_type&) BOOST_ASIO_NOEXCEPT
|
||||
: head_(system_executor())
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
head_.reset();
|
||||
}
|
||||
|
||||
typedef system_executor head_type;
|
||||
composed_work_guard<system_executor> head_;
|
||||
};
|
||||
|
||||
template <typename Head>
|
||||
struct composed_work<void(Head)>
|
||||
{
|
||||
typedef composed_io_executors<void(Head)> executors_type;
|
||||
|
||||
explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
|
||||
: head_(ex.head_)
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
head_.reset();
|
||||
}
|
||||
|
||||
typedef Head head_type;
|
||||
composed_work_guard<Head> head_;
|
||||
};
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
struct composed_work<void(Head, Tail...)>
|
||||
{
|
||||
typedef composed_io_executors<void(Head, Tail...)> executors_type;
|
||||
|
||||
explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
|
||||
: head_(ex.head_),
|
||||
tail_(ex.tail_)
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
head_.reset();
|
||||
tail_.reset();
|
||||
}
|
||||
|
||||
typedef Head head_type;
|
||||
composed_work_guard<Head> head_;
|
||||
composed_work<void(Tail...)> tail_;
|
||||
};
|
||||
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
|
||||
template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
|
||||
struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
|
||||
{ \
|
||||
typedef composed_io_executors<void(Head, \
|
||||
BOOST_ASIO_VARIADIC_TARGS(n))> executors_type; \
|
||||
\
|
||||
explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT \
|
||||
: head_(ex.head_), \
|
||||
tail_(ex.tail_) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
void reset() \
|
||||
{ \
|
||||
head_.reset(); \
|
||||
tail_.reset(); \
|
||||
} \
|
||||
\
|
||||
typedef Head head_type; \
|
||||
composed_work_guard<Head> head_; \
|
||||
composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
|
||||
}; \
|
||||
/**/
|
||||
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
|
||||
#undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename IoObject>
|
||||
inline typename IoObject::executor_type
|
||||
get_composed_io_executor(IoObject& io_object,
|
||||
typename enable_if<
|
||||
!is_executor<IoObject>::value
|
||||
>::type* = 0,
|
||||
typename enable_if<
|
||||
!execution::is_executor<IoObject>::value
|
||||
>::type* = 0)
|
||||
{
|
||||
return io_object.get_executor();
|
||||
}
|
||||
|
||||
template <typename Executor>
|
||||
inline const Executor& get_composed_io_executor(const Executor& ex,
|
||||
typename enable_if<
|
||||
is_executor<Executor>::value
|
||||
|| execution::is_executor<Executor>::value
|
||||
>::type* = 0)
|
||||
{
|
||||
return ex;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_COMPOSED_WORK_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/concurrency_hint.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/conditionally_enabled_event.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -65,6 +65,14 @@ public:
|
||||
event_.unlock_and_signal_one(lock);
|
||||
}
|
||||
|
||||
// Unlock the mutex and signal one waiter who may destroy us.
|
||||
void unlock_and_signal_one_for_destruction(
|
||||
conditionally_enabled_mutex::scoped_lock& lock)
|
||||
{
|
||||
if (lock.mutex_.enabled_)
|
||||
event_.unlock_and_signal_one(lock);
|
||||
}
|
||||
|
||||
// If there's a waiter, unlock the mutex and signal it.
|
||||
bool maybe_unlock_and_signal_one(
|
||||
conditionally_enabled_mutex::scoped_lock& lock)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/conditionally_enabled_mutex.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
// detail/consuming_buffers.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
|
||||
#include <boost/asio/detail/limits.hpp>
|
||||
#include <boost/asio/registered_buffer.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -270,6 +271,42 @@ public:
|
||||
|
||||
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
|
||||
template <>
|
||||
class consuming_buffers<mutable_buffer,
|
||||
mutable_registered_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<mutable_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_registered_buffer& buffer)
|
||||
: consuming_single_buffer<mutable_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer,
|
||||
mutable_registered_buffer, const mutable_buffer*>
|
||||
: public consuming_single_buffer<mutable_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const mutable_registered_buffer& buffer)
|
||||
: consuming_single_buffer<mutable_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class consuming_buffers<const_buffer,
|
||||
const_registered_buffer, const const_buffer*>
|
||||
: public consuming_single_buffer<const_registered_buffer>
|
||||
{
|
||||
public:
|
||||
explicit consuming_buffers(const const_registered_buffer& buffer)
|
||||
: consuming_single_buffer<const_registered_buffer>(buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Buffer, typename Elem>
|
||||
class consuming_buffers<Buffer, boost::array<Elem, 2>,
|
||||
typename boost::array<Elem, 2>::const_iterator>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/cstddef.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/cstdint.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -39,6 +39,7 @@ using std::int64_t;
|
||||
using std::int_least64_t;
|
||||
using std::uint64_t;
|
||||
using std::uint_least64_t;
|
||||
using std::uintptr_t;
|
||||
using std::uintmax_t;
|
||||
#else // defined(BOOST_ASIO_HAS_CSTDINT)
|
||||
using boost::int16_t;
|
||||
@@ -53,6 +54,7 @@ using boost::int64_t;
|
||||
using boost::int_least64_t;
|
||||
using boost::uint64_t;
|
||||
using boost::uint_least64_t;
|
||||
using boost::uintptr_t;
|
||||
using boost::uintmax_t;
|
||||
#endif // defined(BOOST_ASIO_HAS_CSTDINT)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/date_time_fwd.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/deadline_timer_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/asio/associated_cancellation_slot.hpp>
|
||||
#include <boost/asio/cancellation_type.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/execution_context.hpp>
|
||||
#include <boost/asio/detail/bind_handler.hpp>
|
||||
@@ -98,7 +100,7 @@ public:
|
||||
cancel(impl, ec);
|
||||
}
|
||||
|
||||
// Move-construct a new serial port implementation.
|
||||
// Move-construct a new timer implementation.
|
||||
void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
@@ -111,7 +113,7 @@ public:
|
||||
other_impl.might_have_pending_waits = false;
|
||||
}
|
||||
|
||||
// Move-assign from another serial port implementation.
|
||||
// Move-assign from another timer implementation.
|
||||
void move_assign(implementation_type& impl,
|
||||
deadline_timer_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
@@ -130,6 +132,21 @@ public:
|
||||
other_impl.might_have_pending_waits = false;
|
||||
}
|
||||
|
||||
// Move-construct a new timer implementation.
|
||||
void converting_move_construct(implementation_type& impl,
|
||||
deadline_timer_service&, implementation_type& other_impl)
|
||||
{
|
||||
move_construct(impl, other_impl);
|
||||
}
|
||||
|
||||
// Move-assign from another timer implementation.
|
||||
void converting_move_assign(implementation_type& impl,
|
||||
deadline_timer_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
move_assign(impl, other_service, other_impl);
|
||||
}
|
||||
|
||||
// Cancel any asynchronous wait operations associated with the timer.
|
||||
std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
|
||||
{
|
||||
@@ -231,12 +248,22 @@ public:
|
||||
void async_wait(implementation_type& impl,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
typename associated_cancellation_slot<Handler>::type slot
|
||||
= boost::asio::get_associated_cancellation_slot(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef wait_handler<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { boost::asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
// Optionally register for per-operation cancellation.
|
||||
if (slot.is_connected())
|
||||
{
|
||||
p.p->cancellation_key_ =
|
||||
&slot.template emplace<op_cancellation>(this, &impl.timer_data);
|
||||
}
|
||||
|
||||
impl.might_have_pending_waits = true;
|
||||
|
||||
BOOST_ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
@@ -266,6 +293,34 @@ private:
|
||||
#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
}
|
||||
|
||||
// Helper class used to implement per-operation cancellation.
|
||||
class op_cancellation
|
||||
{
|
||||
public:
|
||||
op_cancellation(deadline_timer_service* s,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* p)
|
||||
: service_(s),
|
||||
timer_data_(p)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(cancellation_type_t type)
|
||||
{
|
||||
if (!!(type &
|
||||
(cancellation_type::terminal
|
||||
| cancellation_type::partial
|
||||
| cancellation_type::total)))
|
||||
{
|
||||
service_->scheduler_.cancel_timer_by_key(
|
||||
service_->timer_queue_, timer_data_, this);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
deadline_timer_service* service_;
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer_data_;
|
||||
};
|
||||
|
||||
// The queue of timers.
|
||||
timer_queue<Time_Traits> timer_queue_;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/dependent_type.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/descriptor_ops.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <cstddef>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/asio/detail/cstdint.hpp>
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
@@ -51,18 +52,26 @@ enum
|
||||
|
||||
typedef unsigned char state_type;
|
||||
|
||||
template <typename ReturnType>
|
||||
inline ReturnType error_wrapper(ReturnType return_value,
|
||||
boost::system::error_code& ec)
|
||||
inline void get_last_error(
|
||||
boost::system::error_code& ec, bool is_error_condition)
|
||||
{
|
||||
ec = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
return return_value;
|
||||
if (!is_error_condition)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASIO_DECL int open(const char* path, int flags,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL int open(const char* path, int flags, unsigned mode,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL int close(int d, state_type& state,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
@@ -77,17 +86,66 @@ typedef iovec buf;
|
||||
BOOST_ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
std::size_t count, bool all_empty, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_read1(int d, state_type state, void* data,
|
||||
std::size_t size, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_read1(int d, void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_write(int d, state_type state,
|
||||
const buf* bufs, std::size_t count, bool all_empty,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_write1(int d, state_type state,
|
||||
const void* data, std::size_t size, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_write(int d,
|
||||
const buf* bufs, std::size_t count,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_write1(int d,
|
||||
const void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_FILE)
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_read_at(int d, state_type state,
|
||||
uint64_t offset, buf* bufs, std::size_t count, bool all_empty,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_read_at1(int d, state_type state,
|
||||
uint64_t offset, void* data, std::size_t size,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_read_at(int d, uint64_t offset,
|
||||
buf* bufs, std::size_t count, boost::system::error_code& ec,
|
||||
std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_read_at1(int d, uint64_t offset,
|
||||
void* data, std::size_t size, boost::system::error_code& ec,
|
||||
std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_write_at(int d, state_type state,
|
||||
uint64_t offset, const buf* bufs, std::size_t count, bool all_empty,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL std::size_t sync_write_at1(int d, state_type state,
|
||||
uint64_t offset, const void* data, std::size_t size,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_write_at(int d,
|
||||
uint64_t offset, const buf* bufs, std::size_t count,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
BOOST_ASIO_DECL bool non_blocking_write_at1(int d,
|
||||
uint64_t offset, const void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_FILE)
|
||||
|
||||
BOOST_ASIO_DECL int ioctl(int d, state_type& state, long cmd,
|
||||
ioctl_arg_type* arg, boost::system::error_code& ec);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/descriptor_read_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <boost/asio/detail/handler_work.hpp>
|
||||
#include <boost/asio/detail/memory.hpp>
|
||||
#include <boost/asio/detail/reactor_op.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -37,9 +38,11 @@ template <typename MutableBufferSequence>
|
||||
class descriptor_read_op_base : public reactor_op
|
||||
{
|
||||
public:
|
||||
descriptor_read_op_base(int descriptor,
|
||||
const MutableBufferSequence& buffers, func_type complete_func)
|
||||
: reactor_op(&descriptor_read_op_base::do_perform, complete_func),
|
||||
descriptor_read_op_base(const boost::system::error_code& success_ec,
|
||||
int descriptor, const MutableBufferSequence& buffers,
|
||||
func_type complete_func)
|
||||
: reactor_op(success_ec,
|
||||
&descriptor_read_op_base::do_perform, complete_func),
|
||||
descriptor_(descriptor),
|
||||
buffers_(buffers)
|
||||
{
|
||||
@@ -47,14 +50,27 @@ public:
|
||||
|
||||
static status do_perform(reactor_op* base)
|
||||
{
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));
|
||||
|
||||
buffer_sequence_adapter<boost::asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(o->buffers_);
|
||||
typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs_type;
|
||||
|
||||
status result = descriptor_ops::non_blocking_read(o->descriptor_,
|
||||
bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
|
||||
? done : not_done;
|
||||
status result;
|
||||
if (bufs_type::is_single_buffer)
|
||||
{
|
||||
result = descriptor_ops::non_blocking_read1(o->descriptor_,
|
||||
bufs_type::first(o->buffers_).data(),
|
||||
bufs_type::first(o->buffers_).size(),
|
||||
o->ec_, o->bytes_transferred_) ? done : not_done;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs_type bufs(o->buffers_);
|
||||
result = descriptor_ops::non_blocking_read(o->descriptor_,
|
||||
bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
|
||||
? done : not_done;
|
||||
}
|
||||
|
||||
BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_read",
|
||||
o->ec_, o->bytes_transferred_));
|
||||
@@ -72,16 +88,19 @@ class descriptor_read_op
|
||||
: public descriptor_read_op_base<MutableBufferSequence>
|
||||
{
|
||||
public:
|
||||
typedef Handler handler_type;
|
||||
typedef IoExecutor io_executor_type;
|
||||
|
||||
BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
|
||||
|
||||
descriptor_read_op(int descriptor, const MutableBufferSequence& buffers,
|
||||
descriptor_read_op(const boost::system::error_code& success_ec,
|
||||
int descriptor, const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: descriptor_read_op_base<MutableBufferSequence>(
|
||||
: descriptor_read_op_base<MutableBufferSequence>(success_ec,
|
||||
descriptor, buffers, &descriptor_read_op::do_complete),
|
||||
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
work_(handler_, io_ex)
|
||||
{
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@@ -89,12 +108,19 @@ public:
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
|
||||
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
handler_work<Handler, IoExecutor> w(
|
||||
BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
|
||||
o->work_));
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(o->ec_);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
@@ -116,9 +142,41 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void do_immediate(operation* base, bool, const void* io_ex)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
|
||||
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
immediate_handler_work<Handler, IoExecutor> w(
|
||||
BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
|
||||
o->work_));
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(o->ec_);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder2<Handler, boost::system::error_code, std::size_t>
|
||||
handler(o->handler_, o->ec_, o->bytes_transferred_);
|
||||
p.h = boost::asio::detail::addressof(handler.handler_);
|
||||
p.reset();
|
||||
|
||||
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
|
||||
w.complete(handler, handler.handler_, io_ex);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_END;
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
handler_work<Handler, IoExecutor> work_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/descriptor_write_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -37,9 +37,11 @@ template <typename ConstBufferSequence>
|
||||
class descriptor_write_op_base : public reactor_op
|
||||
{
|
||||
public:
|
||||
descriptor_write_op_base(int descriptor,
|
||||
const ConstBufferSequence& buffers, func_type complete_func)
|
||||
: reactor_op(&descriptor_write_op_base::do_perform, complete_func),
|
||||
descriptor_write_op_base(const boost::system::error_code& success_ec,
|
||||
int descriptor, const ConstBufferSequence& buffers,
|
||||
func_type complete_func)
|
||||
: reactor_op(success_ec,
|
||||
&descriptor_write_op_base::do_perform, complete_func),
|
||||
descriptor_(descriptor),
|
||||
buffers_(buffers)
|
||||
{
|
||||
@@ -47,14 +49,27 @@ public:
|
||||
|
||||
static status do_perform(reactor_op* base)
|
||||
{
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));
|
||||
|
||||
buffer_sequence_adapter<boost::asio::const_buffer,
|
||||
ConstBufferSequence> bufs(o->buffers_);
|
||||
typedef buffer_sequence_adapter<boost::asio::const_buffer,
|
||||
ConstBufferSequence> bufs_type;
|
||||
|
||||
status result = descriptor_ops::non_blocking_write(o->descriptor_,
|
||||
bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
|
||||
? done : not_done;
|
||||
status result;
|
||||
if (bufs_type::is_single_buffer)
|
||||
{
|
||||
result = descriptor_ops::non_blocking_write1(o->descriptor_,
|
||||
bufs_type::first(o->buffers_).data(),
|
||||
bufs_type::first(o->buffers_).size(),
|
||||
o->ec_, o->bytes_transferred_) ? done : not_done;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs_type bufs(o->buffers_);
|
||||
result = descriptor_ops::non_blocking_write(o->descriptor_,
|
||||
bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
|
||||
? done : not_done;
|
||||
}
|
||||
|
||||
BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_write",
|
||||
o->ec_, o->bytes_transferred_));
|
||||
@@ -72,16 +87,19 @@ class descriptor_write_op
|
||||
: public descriptor_write_op_base<ConstBufferSequence>
|
||||
{
|
||||
public:
|
||||
typedef Handler handler_type;
|
||||
typedef IoExecutor io_executor_type;
|
||||
|
||||
BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);
|
||||
|
||||
descriptor_write_op(int descriptor, const ConstBufferSequence& buffers,
|
||||
descriptor_write_op(const boost::system::error_code& success_ec,
|
||||
int descriptor, const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: descriptor_write_op_base<ConstBufferSequence>(
|
||||
: descriptor_write_op_base<ConstBufferSequence>(success_ec,
|
||||
descriptor, buffers, &descriptor_write_op::do_complete),
|
||||
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
work_(handler_, io_ex)
|
||||
{
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@@ -89,12 +107,19 @@ public:
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
|
||||
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
handler_work<Handler, IoExecutor> w(
|
||||
BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
|
||||
o->work_));
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(o->ec_);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
@@ -116,9 +141,41 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void do_immediate(operation* base, bool, const void* io_ex)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
|
||||
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
|
||||
|
||||
BOOST_ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
immediate_handler_work<Handler, IoExecutor> w(
|
||||
BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
|
||||
o->work_));
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(o->ec_);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder2<Handler, boost::system::error_code, std::size_t>
|
||||
handler(o->handler_, o->ec_, o->bytes_transferred_);
|
||||
p.h = boost::asio::detail::addressof(handler.handler_);
|
||||
p.reset();
|
||||
|
||||
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
|
||||
w.complete(handler, handler.handler_, io_ex);
|
||||
BOOST_ASIO_HANDLER_INVOCATION_END;
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
handler_work<Handler, IoExecutor> work_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <boost/asio/detail/op_queue.hpp>
|
||||
#include <boost/asio/detail/reactor_op.hpp>
|
||||
#include <boost/asio/detail/reactor_op_queue.hpp>
|
||||
#include <boost/asio/detail/scheduler_task.hpp>
|
||||
#include <boost/asio/detail/select_interrupter.hpp>
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
#include <boost/asio/detail/timer_queue_base.hpp>
|
||||
@@ -42,7 +43,8 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class dev_poll_reactor
|
||||
: public execution_context_service_base<dev_poll_reactor>
|
||||
: public execution_context_service_base<dev_poll_reactor>,
|
||||
public scheduler_task
|
||||
{
|
||||
public:
|
||||
enum op_types { read_op = 0, write_op = 1,
|
||||
@@ -85,22 +87,43 @@ public:
|
||||
per_descriptor_data& source_descriptor_data);
|
||||
|
||||
// Post a reactor operation for immediate completion.
|
||||
void post_immediate_completion(reactor_op* op, bool is_continuation)
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
void post_immediate_completion(operation* op, bool is_continuation) const;
|
||||
|
||||
// Post a reactor operation for immediate completion.
|
||||
BOOST_ASIO_DECL static void call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
|
||||
per_descriptor_data&, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative);
|
||||
bool is_continuation, bool allow_speculative,
|
||||
void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
void start_op(int op_type, socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
{
|
||||
start_op(op_type, descriptor, descriptor_data,
|
||||
op, is_continuation, allow_speculative,
|
||||
&dev_poll_reactor::call_post_immediate_completion, this);
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the given descriptor. The
|
||||
// handlers associated with the descriptor will be invoked with the
|
||||
// operation_aborted error.
|
||||
BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
|
||||
|
||||
// Cancel all operations associated with the given descriptor and key. The
|
||||
// handlers associated with the descriptor will be invoked with the
|
||||
// operation_aborted error.
|
||||
BOOST_ASIO_DECL void cancel_ops_by_key(socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data,
|
||||
int op_type, void* cancellation_key);
|
||||
|
||||
// Cancel any operations that are running against the descriptor and remove
|
||||
// its registration from the reactor. The reactor resources associated with
|
||||
// the descriptor must be released by calling cleanup_descriptor_data.
|
||||
@@ -139,6 +162,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Cancel the timer operations associated with the given key.
|
||||
template <typename Time_Traits>
|
||||
void cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key);
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/epoll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <boost/asio/detail/object_pool.hpp>
|
||||
#include <boost/asio/detail/op_queue.hpp>
|
||||
#include <boost/asio/detail/reactor_op.hpp>
|
||||
#include <boost/asio/detail/scheduler_task.hpp>
|
||||
#include <boost/asio/detail/select_interrupter.hpp>
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
#include <boost/asio/detail/timer_queue_base.hpp>
|
||||
@@ -43,7 +44,8 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class epoll_reactor
|
||||
: public execution_context_service_base<epoll_reactor>
|
||||
: public execution_context_service_base<epoll_reactor>,
|
||||
public scheduler_task
|
||||
{
|
||||
private:
|
||||
// The mutex type used by this reactor.
|
||||
@@ -115,16 +117,30 @@ public:
|
||||
per_descriptor_data& source_descriptor_data);
|
||||
|
||||
// Post a reactor operation for immediate completion.
|
||||
void post_immediate_completion(reactor_op* op, bool is_continuation)
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
void post_immediate_completion(operation* op, bool is_continuation) const;
|
||||
|
||||
// Post a reactor operation for immediate completion.
|
||||
BOOST_ASIO_DECL static void call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative);
|
||||
bool is_continuation, bool allow_speculative,
|
||||
void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
void start_op(int op_type, socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
{
|
||||
start_op(op_type, descriptor, descriptor_data,
|
||||
op, is_continuation, allow_speculative,
|
||||
&epoll_reactor::call_post_immediate_completion, this);
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the given descriptor. The
|
||||
// handlers associated with the descriptor will be invoked with the
|
||||
@@ -132,6 +148,13 @@ public:
|
||||
BOOST_ASIO_DECL void cancel_ops(socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data);
|
||||
|
||||
// Cancel all operations associated with the given descriptor and key. The
|
||||
// handlers associated with the descriptor will be invoked with the
|
||||
// operation_aborted error.
|
||||
BOOST_ASIO_DECL void cancel_ops_by_key(socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data,
|
||||
int op_type, void* cancellation_key);
|
||||
|
||||
// Cancel any operations that are running against the descriptor and remove
|
||||
// its registration from the reactor. The reactor resources associated with
|
||||
// the descriptor must be released by calling cleanup_descriptor_data.
|
||||
@@ -171,6 +194,12 @@ public:
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
|
||||
|
||||
// Cancel the timer operations associated with the given key.
|
||||
template <typename Time_Traits>
|
||||
void cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key);
|
||||
|
||||
// Move the timer operations associated with the given timer.
|
||||
template <typename Time_Traits>
|
||||
void move_timer(timer_queue<Time_Traits>& queue,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/event.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/eventfd_select_interrupter.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
// Interrupt the select call.
|
||||
BOOST_ASIO_DECL void interrupt();
|
||||
|
||||
// Reset the select interrupt. Returns true if the call was interrupted.
|
||||
// Reset the select interrupter. Returns true if the reset was successful.
|
||||
BOOST_ASIO_DECL bool reset();
|
||||
|
||||
// Get the read descriptor to be passed to select.
|
||||
|
||||
42
linx64/include/boost/asio/detail/exception.hpp
Normal file
42
linx64/include/boost/asio/detail/exception.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// detail/exception.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_EXCEPTION_HPP
|
||||
#define BOOST_ASIO_DETAIL_EXCEPTION_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
# include <exception>
|
||||
#else // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
# include <boost/exception_ptr.hpp>
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
using std::exception_ptr;
|
||||
using std::current_exception;
|
||||
using std::rethrow_exception;
|
||||
#else // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
using boost::exception_ptr;
|
||||
using boost::current_exception;
|
||||
using boost::rethrow_exception;
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_EXCEPTION_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/executor_function.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/memory.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -24,57 +26,80 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class executor_function_base
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
// Lightweight, move-only function object wrapper.
|
||||
class executor_function
|
||||
{
|
||||
public:
|
||||
void complete()
|
||||
template <typename F, typename Alloc>
|
||||
explicit executor_function(F f, const Alloc& a)
|
||||
{
|
||||
func_(this, true);
|
||||
// Allocate and construct an object to wrap the function.
|
||||
typedef impl<F, Alloc> impl_type;
|
||||
typename impl_type::ptr p = {
|
||||
detail::addressof(a), impl_type::ptr::allocate(a), 0 };
|
||||
impl_ = new (p.v) impl_type(BOOST_ASIO_MOVE_CAST(F)(f), a);
|
||||
p.v = 0;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
executor_function(executor_function&& other) BOOST_ASIO_NOEXCEPT
|
||||
: impl_(other.impl_)
|
||||
{
|
||||
func_(this, false);
|
||||
other.impl_ = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef void (*func_type)(executor_function_base*, bool);
|
||||
|
||||
executor_function_base(func_type func)
|
||||
: func_(func)
|
||||
~executor_function()
|
||||
{
|
||||
if (impl_)
|
||||
impl_->complete_(impl_, false);
|
||||
}
|
||||
|
||||
// Prevents deletion through this type.
|
||||
~executor_function_base()
|
||||
void operator()()
|
||||
{
|
||||
if (impl_)
|
||||
{
|
||||
impl_base* i = impl_;
|
||||
impl_ = 0;
|
||||
i->complete_(i, true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
func_type func_;
|
||||
};
|
||||
|
||||
template <typename Function, typename Alloc>
|
||||
class executor_function : public executor_function_base
|
||||
{
|
||||
public:
|
||||
BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
|
||||
thread_info_base::executor_function_tag, executor_function);
|
||||
|
||||
template <typename F>
|
||||
executor_function(BOOST_ASIO_MOVE_ARG(F) f, const Alloc& allocator)
|
||||
: executor_function_base(&executor_function::do_complete),
|
||||
function_(BOOST_ASIO_MOVE_CAST(F)(f)),
|
||||
allocator_(allocator)
|
||||
// Base class for polymorphic function implementations.
|
||||
struct impl_base
|
||||
{
|
||||
}
|
||||
void (*complete_)(impl_base*, bool);
|
||||
};
|
||||
|
||||
static void do_complete(executor_function_base* base, bool call)
|
||||
// Polymorphic function implementation.
|
||||
template <typename Function, typename Alloc>
|
||||
struct impl : impl_base
|
||||
{
|
||||
BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
|
||||
thread_info_base::executor_function_tag, impl);
|
||||
|
||||
template <typename F>
|
||||
impl(BOOST_ASIO_MOVE_ARG(F) f, const Alloc& a)
|
||||
: function_(BOOST_ASIO_MOVE_CAST(F)(f)),
|
||||
allocator_(a)
|
||||
{
|
||||
complete_ = &executor_function::complete<Function, Alloc>;
|
||||
}
|
||||
|
||||
Function function_;
|
||||
Alloc allocator_;
|
||||
};
|
||||
|
||||
// Helper to complete function invocation.
|
||||
template <typename Function, typename Alloc>
|
||||
static void complete(impl_base* base, bool call)
|
||||
{
|
||||
// Take ownership of the function object.
|
||||
executor_function* o(static_cast<executor_function*>(base));
|
||||
Alloc allocator(o->allocator_);
|
||||
ptr p = { detail::addressof(allocator), o, o };
|
||||
impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));
|
||||
Alloc allocator(i->allocator_);
|
||||
typename impl<Function, Alloc>::ptr p = {
|
||||
detail::addressof(allocator), i, i };
|
||||
|
||||
// Make a copy of the function so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
@@ -82,19 +107,94 @@ public:
|
||||
// associated with the function. Consequently, a local copy of the function
|
||||
// is required to ensure that any owning sub-object remains valid until
|
||||
// after we have deallocated the memory here.
|
||||
Function function(BOOST_ASIO_MOVE_CAST(Function)(o->function_));
|
||||
Function function(BOOST_ASIO_MOVE_CAST(Function)(i->function_));
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (call)
|
||||
{
|
||||
function();
|
||||
boost_asio_handler_invoke_helpers::invoke(function, function);
|
||||
}
|
||||
}
|
||||
|
||||
impl_base* impl_;
|
||||
};
|
||||
|
||||
#else // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
// Not so lightweight, copyable function object wrapper.
|
||||
class executor_function
|
||||
{
|
||||
public:
|
||||
template <typename F, typename Alloc>
|
||||
explicit executor_function(const F& f, const Alloc&)
|
||||
: impl_(new impl<typename decay<F>::type>(f))
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
impl_->complete_(impl_.get());
|
||||
}
|
||||
|
||||
private:
|
||||
Function function_;
|
||||
Alloc allocator_;
|
||||
// Base class for polymorphic function implementations.
|
||||
struct impl_base
|
||||
{
|
||||
void (*complete_)(impl_base*);
|
||||
};
|
||||
|
||||
// Polymorphic function implementation.
|
||||
template <typename F>
|
||||
struct impl : impl_base
|
||||
{
|
||||
impl(const F& f)
|
||||
: function_(f)
|
||||
{
|
||||
complete_ = &executor_function::complete<F>;
|
||||
}
|
||||
|
||||
F function_;
|
||||
};
|
||||
|
||||
// Helper to complete function invocation.
|
||||
template <typename F>
|
||||
static void complete(impl_base* i)
|
||||
{
|
||||
static_cast<impl<F>*>(i)->function_();
|
||||
}
|
||||
|
||||
shared_ptr<impl_base> impl_;
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
// Lightweight, non-owning, copyable function object wrapper.
|
||||
class executor_function_view
|
||||
{
|
||||
public:
|
||||
template <typename F>
|
||||
explicit executor_function_view(F& f) BOOST_ASIO_NOEXCEPT
|
||||
: complete_(&executor_function_view::complete<F>),
|
||||
function_(&f)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
complete_(function_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Helper to complete function invocation.
|
||||
template <typename F>
|
||||
static void complete(void* f)
|
||||
{
|
||||
(*static_cast<F*>(f))();
|
||||
}
|
||||
|
||||
void (*complete_)(void*);
|
||||
void* function_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/executor_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
BOOST_ASIO_ASSUME(base != 0);
|
||||
executor_op* o(static_cast<executor_op*>(base));
|
||||
Alloc allocator(o->allocator_);
|
||||
ptr p = { detail::addressof(allocator), o, o };
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/fd_set_adapter.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/functional.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -34,6 +34,12 @@ using boost::function;
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||
using std::ref;
|
||||
using std::reference_wrapper;
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/future.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/gcc_arm_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/gcc_hppa_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/gcc_sync_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/gcc_x86_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
{
|
||||
int r = 0, m = 1;
|
||||
__asm__ __volatile__ (
|
||||
"xchgl %0, %1" :
|
||||
"xchg{l} %0, %1" :
|
||||
"=r"(r), "=m"(m) :
|
||||
"0"(1), "m"(m) :
|
||||
"memory", "cc");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/global.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_alloc_helpers.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/asio/detail/memory.hpp>
|
||||
#include <boost/asio/detail/noncopyable.hpp>
|
||||
#include <boost/asio/detail/recycling_allocator.hpp>
|
||||
#include <boost/asio/detail/thread_info_base.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
|
||||
@@ -29,12 +30,45 @@
|
||||
// boost_asio_handler_alloc_helpers namespace is defined here for that purpose.
|
||||
namespace boost_asio_handler_alloc_helpers {
|
||||
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
template <typename Handler>
|
||||
inline void* allocate(std::size_t s, Handler& h)
|
||||
inline void error_if_hooks_are_defined(Handler& h)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
// If you get an error here it is because some of your handlers still
|
||||
// overload asio_handler_allocate, but this hook is no longer used.
|
||||
(void)static_cast<boost::asio::asio_handler_allocate_is_no_longer_used>(
|
||||
asio_handler_allocate(static_cast<std::size_t>(0),
|
||||
boost::asio::detail::addressof(h)));
|
||||
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
// If you get an error here it is because some of your handlers still
|
||||
// overload asio_handler_deallocate, but this hook is no longer used.
|
||||
(void)static_cast<boost::asio::asio_handler_deallocate_is_no_longer_used>(
|
||||
asio_handler_deallocate(static_cast<void*>(0),
|
||||
static_cast<std::size_t>(0), boost::asio::detail::addressof(h)));
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Handler>
|
||||
inline void* allocate(std::size_t s, Handler& h,
|
||||
std::size_t align = BOOST_ASIO_DEFAULT_ALIGN)
|
||||
{
|
||||
#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
|
||||
return ::operator new(s);
|
||||
return boost::asio::aligned_new(align, s);
|
||||
#elif defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
// The asio_handler_allocate hook is no longer used to obtain memory.
|
||||
(void)&error_if_hooks_are_defined<Handler>;
|
||||
(void)h;
|
||||
# if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
return boost::asio::detail::thread_info_base::allocate(
|
||||
boost::asio::detail::thread_context::top_of_thread_call_stack(),
|
||||
s, align);
|
||||
# else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
return boost::asio::aligned_new(align, s);
|
||||
# endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
#else
|
||||
(void)align;
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(s, boost::asio::detail::addressof(h));
|
||||
#endif
|
||||
@@ -44,7 +78,18 @@ template <typename Handler>
|
||||
inline void deallocate(void* p, std::size_t s, Handler& h)
|
||||
{
|
||||
#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
|
||||
::operator delete(p);
|
||||
boost::asio::aligned_delete(p);
|
||||
#elif defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
// The asio_handler_allocate hook is no longer used to obtain memory.
|
||||
(void)&error_if_hooks_are_defined<Handler>;
|
||||
(void)h;
|
||||
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
boost::asio::detail::thread_info_base::deallocate(
|
||||
boost::asio::detail::thread_context::top_of_thread_call_stack(), p, s);
|
||||
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
(void)s;
|
||||
boost::asio::aligned_delete(p);
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
#else
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(p, s, boost::asio::detail::addressof(h));
|
||||
@@ -83,7 +128,8 @@ public:
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
return static_cast<T*>(
|
||||
boost_asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));
|
||||
boost_asio_handler_alloc_helpers::allocate(
|
||||
sizeof(T) * n, handler_, BOOST_ASIO_ALIGNOF(T)));
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_cont_helpers.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_invoke_helpers.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -26,12 +26,29 @@
|
||||
// namespace is defined here for that purpose.
|
||||
namespace boost_asio_handler_invoke_helpers {
|
||||
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
template <typename Function, typename Context>
|
||||
inline void error_if_hook_is_defined(Function& function, Context& context)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
// If you get an error here it is because some of your handlers still
|
||||
// overload asio_handler_invoke, but this hook is no longer used.
|
||||
(void)static_cast<boost::asio::asio_handler_invoke_is_no_longer_used>(
|
||||
asio_handler_invoke(function, boost::asio::detail::addressof(context)));
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Function, typename Context>
|
||||
inline void invoke(Function& function, Context& context)
|
||||
{
|
||||
#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
|
||||
Function tmp(function);
|
||||
tmp();
|
||||
#elif defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
// The asio_handler_invoke hook is no longer used to invoke the function.
|
||||
(void)&error_if_hook_is_defined<Function, Context>;
|
||||
(void)context;
|
||||
function();
|
||||
#else
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, boost::asio::detail::addressof(context));
|
||||
@@ -44,6 +61,12 @@ inline void invoke(const Function& function, Context& context)
|
||||
#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
|
||||
Function tmp(function);
|
||||
tmp();
|
||||
#elif defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
// The asio_handler_invoke hook is no longer used to invoke the function.
|
||||
(void)&error_if_hook_is_defined<const Function, Context>;
|
||||
(void)context;
|
||||
Function tmp(function);
|
||||
tmp();
|
||||
#else
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(function, boost::asio::detail::addressof(context));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_tracking.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -90,6 +90,28 @@ public:
|
||||
// Initialise the tracking system.
|
||||
BOOST_ASIO_DECL static void init();
|
||||
|
||||
class location
|
||||
{
|
||||
public:
|
||||
// Constructor adds a location to the stack.
|
||||
BOOST_ASIO_DECL explicit location(const char* file,
|
||||
int line, const char* func);
|
||||
|
||||
// Destructor removes a location from the stack.
|
||||
BOOST_ASIO_DECL ~location();
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
location(const location&) BOOST_ASIO_DELETED;
|
||||
location& operator=(const location&) BOOST_ASIO_DELETED;
|
||||
|
||||
friend class handler_tracking;
|
||||
const char* file_;
|
||||
int line_;
|
||||
const char* func_;
|
||||
location* next_;
|
||||
};
|
||||
|
||||
// Record the creation of a tracked handler.
|
||||
BOOST_ASIO_DECL static void creation(
|
||||
execution_context& context, tracked_handler& h,
|
||||
@@ -178,6 +200,9 @@ private:
|
||||
# define BOOST_ASIO_HANDLER_TRACKING_INIT \
|
||||
boost::asio::detail::handler_tracking::init()
|
||||
|
||||
# define BOOST_ASIO_HANDLER_LOCATION(args) \
|
||||
boost::asio::detail::handler_tracking::location tracked_location args
|
||||
|
||||
# define BOOST_ASIO_HANDLER_CREATION(args) \
|
||||
boost::asio::detail::handler_tracking::creation args
|
||||
|
||||
@@ -214,6 +239,7 @@ private:
|
||||
# define BOOST_ASIO_INHERIT_TRACKED_HANDLER
|
||||
# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
|
||||
# define BOOST_ASIO_HANDLER_TRACKING_INIT (void)0
|
||||
# define BOOST_ASIO_HANDLER_LOCATION(loc) (void)0
|
||||
# define BOOST_ASIO_HANDLER_CREATION(args) (void)0
|
||||
# define BOOST_ASIO_HANDLER_COMPLETION(args) (void)0
|
||||
# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_type_requirements.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -65,7 +65,7 @@ template <typename Handler>
|
||||
auto zero_arg_copyable_handler_test(Handler h, void*)
|
||||
-> decltype(
|
||||
sizeof(Handler(static_cast<const Handler&>(h))),
|
||||
((h)()),
|
||||
(BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)()),
|
||||
char(0));
|
||||
|
||||
template <typename Handler>
|
||||
@@ -75,7 +75,7 @@ template <typename Handler, typename Arg1>
|
||||
auto one_arg_handler_test(Handler h, Arg1* a1)
|
||||
-> decltype(
|
||||
sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
|
||||
((h)(*a1)),
|
||||
(BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)),
|
||||
char(0));
|
||||
|
||||
template <typename Handler>
|
||||
@@ -85,7 +85,7 @@ template <typename Handler, typename Arg1, typename Arg2>
|
||||
auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
|
||||
-> decltype(
|
||||
sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
|
||||
((h)(*a1, *a2)),
|
||||
(BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)),
|
||||
char(0));
|
||||
|
||||
template <typename Handler>
|
||||
@@ -95,7 +95,8 @@ template <typename Handler, typename Arg1, typename Arg2>
|
||||
auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
|
||||
-> decltype(
|
||||
sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
|
||||
((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
|
||||
(BOOST_ASIO_MOVE_OR_LVALUE(Handler)(h)(
|
||||
*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
|
||||
char(0));
|
||||
|
||||
template <typename Handler>
|
||||
@@ -117,9 +118,11 @@ template <typename T> const T& clvref(T);
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
template <typename T> T rvref();
|
||||
template <typename T> T rvref(T);
|
||||
template <typename T> T rorlvref();
|
||||
#else // defined(BOOST_ASIO_HAS_MOVE)
|
||||
template <typename T> const T& rvref();
|
||||
template <typename T> const T& rvref(T);
|
||||
template <typename T> T& rorlvref();
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
template <typename T> char argbyv(T);
|
||||
|
||||
@@ -146,7 +149,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::clvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()(), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
|
||||
@@ -171,7 +174,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const std::size_t>()), \
|
||||
@@ -198,7 +201,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const std::size_t>()), \
|
||||
@@ -224,7 +227,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>()), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
@@ -250,7 +253,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::rvref<socket_type>()), \
|
||||
@@ -276,7 +279,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>()), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
@@ -302,7 +305,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const endpoint_type>()), \
|
||||
@@ -329,7 +332,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const iter_type>()), \
|
||||
@@ -356,7 +359,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const range_type>()), \
|
||||
@@ -382,7 +385,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>()), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
@@ -408,7 +411,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const int>()), \
|
||||
@@ -434,7 +437,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>()), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
@@ -460,7 +463,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>(), \
|
||||
boost::asio::detail::lvref<const std::size_t>()), \
|
||||
@@ -486,7 +489,7 @@ struct handler_type_requirements
|
||||
boost::asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
boost::asio::detail::lvref< \
|
||||
boost::asio::detail::rorlvref< \
|
||||
asio_true_handler_type>()( \
|
||||
boost::asio::detail::lvref<const boost::system::error_code>()), \
|
||||
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/handler_work.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -16,94 +16,546 @@
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/associated_allocator.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/associated_immediate_executor.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/initiate_dispatch.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
#include <boost/asio/detail/work_dispatcher.hpp>
|
||||
#include <boost/asio/execution/allocator.hpp>
|
||||
#include <boost/asio/execution/blocking.hpp>
|
||||
#include <boost/asio/execution/execute.hpp>
|
||||
#include <boost/asio/execution/executor.hpp>
|
||||
#include <boost/asio/execution/outstanding_work.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/prefer.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
class executor;
|
||||
class io_context;
|
||||
|
||||
#if !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
class any_completion_executor;
|
||||
class any_io_executor;
|
||||
|
||||
#endif // !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
namespace execution {
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename...> class any_executor;
|
||||
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename, typename, typename, typename, typename,
|
||||
typename, typename, typename, typename> class any_executor;
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
} // namespace execution
|
||||
namespace detail {
|
||||
|
||||
// A helper class template to allow completion handlers to be dispatched
|
||||
// through either the new executors framework or the old invocaton hook. The
|
||||
// primary template uses the new executors framework.
|
||||
template <typename Handler,
|
||||
typename IoExecutor = system_executor, typename HandlerExecutor
|
||||
= typename associated_executor<Handler, IoExecutor>::type>
|
||||
class handler_work
|
||||
template <typename Executor, typename CandidateExecutor = void,
|
||||
typename IoContext = io_context,
|
||||
typename PolymorphicExecutor = executor, typename = void>
|
||||
class handler_work_base
|
||||
{
|
||||
public:
|
||||
explicit handler_work(Handler& handler) BOOST_ASIO_NOEXCEPT
|
||||
: io_executor_(),
|
||||
executor_(boost::asio::get_associated_executor(handler, io_executor_))
|
||||
explicit handler_work_base(int, int, const Executor& ex) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
handler_work(Handler& handler, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
|
||||
: io_executor_(io_ex),
|
||||
executor_(boost::asio::get_associated_executor(handler, io_executor_))
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
|
||||
const OtherExecutor& /*candidate*/) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
static void start(Handler& handler) BOOST_ASIO_NOEXCEPT
|
||||
handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(other.executor_)
|
||||
{
|
||||
HandlerExecutor ex(boost::asio::get_associated_executor(handler));
|
||||
ex.on_work_started();
|
||||
}
|
||||
|
||||
static void start(Handler& handler,
|
||||
const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
|
||||
{
|
||||
HandlerExecutor ex(boost::asio::get_associated_executor(handler, io_ex));
|
||||
ex.on_work_started();
|
||||
io_ex.on_work_started();
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
~handler_work()
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler& handler)
|
||||
{
|
||||
io_executor_.on_work_finished();
|
||||
executor_.on_work_finished();
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost::asio::prefer(executor_,
|
||||
execution::allocator((get_associated_allocator)(handler))
|
||||
).execute(BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
execution::execute(
|
||||
boost::asio::prefer(executor_,
|
||||
execution::allocator((get_associated_allocator)(handler))),
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void complete(Function& function, Handler& handler)
|
||||
private:
|
||||
typedef typename decay<
|
||||
typename prefer_result<Executor,
|
||||
execution::outstanding_work_t::tracked_t
|
||||
>::type
|
||||
>::type executor_type;
|
||||
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
template <typename Executor, typename CandidateExecutor,
|
||||
typename IoContext, typename PolymorphicExecutor>
|
||||
class handler_work_base<Executor, CandidateExecutor,
|
||||
IoContext, PolymorphicExecutor,
|
||||
typename enable_if<
|
||||
!execution::is_executor<Executor>::value
|
||||
&& (!is_same<Executor, PolymorphicExecutor>::value
|
||||
|| !is_same<CandidateExecutor, void>::value)
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
explicit handler_work_base(int, int, const Executor& ex) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(true)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
|
||||
const Executor& candidate) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(ex != candidate)
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
|
||||
const OtherExecutor& /*candidate*/) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(true)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(other.executor_),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
other.owns_work_ = false;
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
~handler_work_base()
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return owns_work_;
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler& handler)
|
||||
{
|
||||
executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function),
|
||||
boost::asio::get_associated_allocator(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
handler_work(const handler_work&);
|
||||
handler_work& operator=(const handler_work&);
|
||||
|
||||
IoExecutor io_executor_;
|
||||
HandlerExecutor executor_;
|
||||
Executor executor_;
|
||||
bool owns_work_;
|
||||
};
|
||||
|
||||
// This specialisation dispatches a handler through the old invocation hook.
|
||||
// The specialisation is not strictly required for correctness, as the
|
||||
// system_executor will dispatch through the hook anyway. However, by doing
|
||||
// this we avoid an extra copy of the handler.
|
||||
template <typename Handler>
|
||||
class handler_work<Handler, system_executor, system_executor>
|
||||
template <typename Executor, typename IoContext, typename PolymorphicExecutor>
|
||||
class handler_work_base<Executor, void, IoContext, PolymorphicExecutor,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
Executor,
|
||||
typename IoContext::executor_type
|
||||
>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
explicit handler_work(Handler&) BOOST_ASIO_NOEXCEPT {}
|
||||
static void start(Handler&) BOOST_ASIO_NOEXCEPT {}
|
||||
~handler_work() {}
|
||||
explicit handler_work_base(int, int, const Executor&)
|
||||
{
|
||||
}
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler& handler)
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
boost_asio_handler_invoke_helpers::invoke(function, handler);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Executor, typename IoContext>
|
||||
class handler_work_base<Executor, void, IoContext, Executor>
|
||||
{
|
||||
public:
|
||||
explicit handler_work_base(int, int, const Executor& ex) BOOST_ASIO_NOEXCEPT
|
||||
#if !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(
|
||||
ex.target_type() == typeid(typename IoContext::executor_type)
|
||||
? Executor() : ex)
|
||||
#else // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(ex)
|
||||
#endif // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
|
||||
const Executor& candidate) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(ex != candidate ? ex : Executor())
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(const Executor& ex,
|
||||
const OtherExecutor&) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(ex)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(other.executor_)
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
~handler_work_base()
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return !!executor_;
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler& handler)
|
||||
{
|
||||
executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function),
|
||||
boost::asio::get_associated_allocator(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
};
|
||||
|
||||
template <
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
typename... SupportableProperties,
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9,
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
typename CandidateExecutor, typename IoContext,
|
||||
typename PolymorphicExecutor>
|
||||
class handler_work_base<
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
execution::any_executor<SupportableProperties...>,
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>,
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
CandidateExecutor, IoContext, PolymorphicExecutor>
|
||||
{
|
||||
public:
|
||||
typedef
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
execution::any_executor<SupportableProperties...>
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
executor_type;
|
||||
|
||||
explicit handler_work_base(int, int,
|
||||
const executor_type& ex) BOOST_ASIO_NOEXCEPT
|
||||
#if !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(
|
||||
ex.target_type() == typeid(typename IoContext::executor_type)
|
||||
? executor_type()
|
||||
: boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
#else // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
#endif // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
{
|
||||
}
|
||||
|
||||
handler_work_base(bool base1_owns_work, const executor_type& ex,
|
||||
const executor_type& candidate) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(
|
||||
!base1_owns_work && ex == candidate
|
||||
? executor_type()
|
||||
: boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,
|
||||
const OtherExecutor& /*candidate*/) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(other.executor_)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return !!executor_;
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler&)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
executor_.execute(BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
execution::execute(executor_, BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
private:
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
template <typename Executor, typename CandidateExecutor,
|
||||
typename IoContext, typename PolymorphicExecutor>
|
||||
class handler_work_base<
|
||||
Executor, CandidateExecutor,
|
||||
IoContext, PolymorphicExecutor,
|
||||
typename enable_if<
|
||||
is_same<Executor, any_completion_executor>::value
|
||||
|| is_same<Executor, any_io_executor>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
typedef Executor executor_type;
|
||||
|
||||
explicit handler_work_base(int, int,
|
||||
const executor_type& ex) BOOST_ASIO_NOEXCEPT
|
||||
#if !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(
|
||||
ex.target_type() == typeid(typename IoContext::executor_type)
|
||||
? executor_type()
|
||||
: boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
#else // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
#endif // !defined(BOOST_ASIO_NO_TYPEID)
|
||||
{
|
||||
}
|
||||
|
||||
handler_work_base(bool base1_owns_work, const executor_type& ex,
|
||||
const executor_type& candidate) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(
|
||||
!base1_owns_work && ex == candidate
|
||||
? executor_type()
|
||||
: boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,
|
||||
const OtherExecutor& /*candidate*/) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(other.executor_)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
|
||||
: executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
bool owns_work() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return !!executor_;
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler>
|
||||
void dispatch(Function& function, Handler&)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
executor_.execute(BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
execution::execute(executor_, BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
|
||||
private:
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
template <typename Handler, typename IoExecutor, typename = void>
|
||||
class handler_work :
|
||||
handler_work_base<IoExecutor>,
|
||||
handler_work_base<typename associated_executor<
|
||||
Handler, IoExecutor>::type, IoExecutor>
|
||||
{
|
||||
public:
|
||||
typedef handler_work_base<IoExecutor> base1_type;
|
||||
typedef handler_work_base<typename associated_executor<
|
||||
Handler, IoExecutor>::type, IoExecutor> base2_type;
|
||||
|
||||
handler_work(Handler& handler, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
|
||||
: base1_type(0, 0, io_ex),
|
||||
base2_type(base1_type::owns_work(),
|
||||
boost::asio::get_associated_executor(handler, io_ex), io_ex)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void complete(Function& function, Handler& handler)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::invoke(function, handler);
|
||||
if (!base1_type::owns_work() && !base2_type::owns_work())
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
boost_asio_handler_invoke_helpers::invoke(function, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
base2_type::dispatch(function, handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class handler_work<
|
||||
Handler, IoExecutor,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
typename associated_executor<Handler,
|
||||
IoExecutor>::asio_associated_executor_is_unspecialised,
|
||||
void
|
||||
>::value
|
||||
>::type> : handler_work_base<IoExecutor>
|
||||
{
|
||||
public:
|
||||
typedef handler_work_base<IoExecutor> base1_type;
|
||||
|
||||
handler_work(Handler&, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
|
||||
: base1_type(0, 0, io_ex)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void complete(Function& function, Handler& handler)
|
||||
{
|
||||
if (!base1_type::owns_work())
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
boost_asio_handler_invoke_helpers::invoke(function, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
base1_type::dispatch(function, handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class immediate_handler_work
|
||||
{
|
||||
public:
|
||||
typedef handler_work<Handler, IoExecutor> handler_work_type;
|
||||
|
||||
explicit immediate_handler_work(BOOST_ASIO_MOVE_ARG(handler_work_type) w)
|
||||
: handler_work_(BOOST_ASIO_MOVE_CAST(handler_work_type)(w))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void complete(Function& function, Handler& handler, const void* io_ex)
|
||||
{
|
||||
typedef typename associated_immediate_executor<Handler, IoExecutor>::type
|
||||
immediate_ex_type;
|
||||
|
||||
immediate_ex_type immediate_ex = (get_associated_immediate_executor)(
|
||||
handler, *static_cast<const IoExecutor*>(io_ex));
|
||||
|
||||
(initiate_dispatch_with_executor<immediate_ex_type>(immediate_ex))(
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
handler_work(const handler_work&);
|
||||
handler_work& operator=(const handler_work&);
|
||||
handler_work_type handler_work_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/hash_map.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/buffer_sequence_adapter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/descriptor_ops.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -33,10 +33,16 @@ namespace descriptor_ops {
|
||||
|
||||
int open(const char* path, int flags, boost::system::error_code& ec)
|
||||
{
|
||||
errno = 0;
|
||||
int result = error_wrapper(::open(path, flags), ec);
|
||||
if (result >= 0)
|
||||
ec = boost::system::error_code();
|
||||
int result = ::open(path, flags);
|
||||
get_last_error(ec, result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
int open(const char* path, int flags,
|
||||
unsigned mode, boost::system::error_code& ec)
|
||||
{
|
||||
int result = ::open(path, flags, mode);
|
||||
get_last_error(ec, result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -45,8 +51,8 @@ int close(int d, state_type& state, boost::system::error_code& ec)
|
||||
int result = 0;
|
||||
if (d != -1)
|
||||
{
|
||||
errno = 0;
|
||||
result = error_wrapper(::close(d), ec);
|
||||
result = ::close(d);
|
||||
get_last_error(ec, result < 0);
|
||||
|
||||
if (result != 0
|
||||
&& (ec == boost::asio::error::would_block
|
||||
@@ -58,23 +64,32 @@ int close(int d, state_type& state, boost::system::error_code& ec)
|
||||
// current OS where this behaviour is seen, Windows, says that the socket
|
||||
// remains open. Therefore we'll put the descriptor back into blocking
|
||||
// mode and have another attempt at closing it.
|
||||
#if defined(__SYMBIAN32__)
|
||||
#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
int flags = ::fcntl(d, F_GETFL, 0);
|
||||
if (flags >= 0)
|
||||
::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
|
||||
#else // defined(__SYMBIAN32__)
|
||||
#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
ioctl_arg_type arg = 0;
|
||||
# if defined(ENOTTY)
|
||||
result = ::ioctl(d, FIONBIO, &arg);
|
||||
get_last_error(ec, result < 0);
|
||||
if (ec.value() == ENOTTY)
|
||||
{
|
||||
int flags = ::fcntl(d, F_GETFL, 0);
|
||||
if (flags >= 0)
|
||||
::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
# else // defined(ENOTTY)
|
||||
::ioctl(d, FIONBIO, &arg);
|
||||
#endif // defined(__SYMBIAN32__)
|
||||
# endif // defined(ENOTTY)
|
||||
#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
state &= ~non_blocking;
|
||||
|
||||
errno = 0;
|
||||
result = error_wrapper(::close(d), ec);
|
||||
result = ::close(d);
|
||||
get_last_error(ec, result < 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
ec = boost::system::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -87,23 +102,36 @@ bool set_user_non_blocking(int d, state_type& state,
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#if defined(__SYMBIAN32__)
|
||||
int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
|
||||
#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
int result = ::fcntl(d, F_GETFL, 0);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result >= 0)
|
||||
{
|
||||
errno = 0;
|
||||
int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
|
||||
result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
|
||||
result = ::fcntl(d, F_SETFL, flag);
|
||||
get_last_error(ec, result < 0);
|
||||
}
|
||||
#else // defined(__SYMBIAN32__)
|
||||
#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
ioctl_arg_type arg = (value ? 1 : 0);
|
||||
int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
|
||||
#endif // defined(__SYMBIAN32__)
|
||||
int result = ::ioctl(d, FIONBIO, &arg);
|
||||
get_last_error(ec, result < 0);
|
||||
# if defined(ENOTTY)
|
||||
if (ec.value() == ENOTTY)
|
||||
{
|
||||
result = ::fcntl(d, F_GETFL, 0);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result >= 0)
|
||||
{
|
||||
int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
|
||||
result = ::fcntl(d, F_SETFL, flag);
|
||||
get_last_error(ec, result < 0);
|
||||
}
|
||||
}
|
||||
# endif // defined(ENOTTY)
|
||||
#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
if (value)
|
||||
state |= user_set_non_blocking;
|
||||
else
|
||||
@@ -137,23 +165,36 @@ bool set_internal_non_blocking(int d, state_type& state,
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#if defined(__SYMBIAN32__)
|
||||
int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
|
||||
#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
int result = ::fcntl(d, F_GETFL, 0);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result >= 0)
|
||||
{
|
||||
errno = 0;
|
||||
int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
|
||||
result = error_wrapper(::fcntl(d, F_SETFL, flag), ec);
|
||||
result = ::fcntl(d, F_SETFL, flag);
|
||||
get_last_error(ec, result < 0);
|
||||
}
|
||||
#else // defined(__SYMBIAN32__)
|
||||
#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
ioctl_arg_type arg = (value ? 1 : 0);
|
||||
int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
|
||||
#endif // defined(__SYMBIAN32__)
|
||||
int result = ::ioctl(d, FIONBIO, &arg);
|
||||
get_last_error(ec, result < 0);
|
||||
# if defined(ENOTTY)
|
||||
if (ec.value() == ENOTTY)
|
||||
{
|
||||
result = ::fcntl(d, F_GETFL, 0);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result >= 0)
|
||||
{
|
||||
int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));
|
||||
result = ::fcntl(d, F_SETFL, flag);
|
||||
get_last_error(ec, result < 0);
|
||||
}
|
||||
}
|
||||
# endif // defined(ENOTTY)
|
||||
#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
if (value)
|
||||
state |= internal_non_blocking;
|
||||
else
|
||||
@@ -176,7 +217,7 @@ std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
// A request to read 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -184,9 +225,54 @@ std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
signed_size_type bytes = error_wrapper(::readv(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_read(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t sync_read1(int d, state_type state, void* data,
|
||||
std::size_t size, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to read 0 bytes on a stream is a no-op.
|
||||
if (size == 0)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::read(d, data, size);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
@@ -217,9 +303,8 @@ bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
errno = 0;
|
||||
signed_size_type bytes = error_wrapper(::readv(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check for end of stream.
|
||||
if (bytes == 0)
|
||||
@@ -228,6 +313,13 @@ bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
@@ -237,15 +329,46 @@ bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation is complete.
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_read1(int d, void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
signed_size_type bytes = ::read(d, data, size);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check for end of stream.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
bytes_transferred = 0;
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -262,7 +385,7 @@ std::size_t sync_write(int d, state_type state, const buf* bufs,
|
||||
// A request to write 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -270,9 +393,47 @@ std::size_t sync_write(int d, state_type state, const buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
signed_size_type bytes = error_wrapper(::writev(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_write(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t sync_write1(int d, state_type state, const void* data,
|
||||
std::size_t size, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to write 0 bytes on a stream is a no-op.
|
||||
if (size == 0)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::write(d, data, size);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
@@ -296,9 +457,15 @@ bool non_blocking_write(int d, const buf* bufs, std::size_t count,
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
errno = 0;
|
||||
signed_size_type bytes = error_wrapper(::writev(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -309,19 +476,360 @@ bool non_blocking_write(int d, const buf* bufs, std::size_t count,
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation is complete.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
bytes_transferred = bytes;
|
||||
}
|
||||
else
|
||||
bytes_transferred = 0;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_write1(int d, const void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
signed_size_type bytes = ::write(d, data, size);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_FILE)
|
||||
|
||||
std::size_t sync_read_at(int d, state_type state, uint64_t offset,
|
||||
buf* bufs, std::size_t count, bool all_empty, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to read 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_read(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t sync_read_at1(int d, state_type state, uint64_t offset,
|
||||
void* data, std::size_t size, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to read 0 bytes on a stream is a no-op.
|
||||
if (size == 0)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::pread(d, data, size, offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_read(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_read_at(int d, uint64_t offset, buf* bufs, std::size_t count,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_read_at1(int d, uint64_t offset, void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
signed_size_type bytes = ::pread(d, data, size, offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = boost::asio::error::eof;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t sync_write_at(int d, state_type state, uint64_t offset,
|
||||
const buf* bufs, std::size_t count, bool all_empty,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to write 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::pwritev(d,
|
||||
bufs, static_cast<int>(count), offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_write(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t sync_write_at1(int d, state_type state, uint64_t offset,
|
||||
const void* data, std::size_t size, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to write 0 bytes on a stream is a no-op.
|
||||
if (size == 0)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
signed_size_type bytes = ::pwrite(d, data, size, offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != boost::asio::error::would_block
|
||||
&& ec != boost::asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_write(d, 0, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_write_at(int d, uint64_t offset,
|
||||
const buf* bufs, std::size_t count,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
signed_size_type bytes = ::pwritev(d,
|
||||
bufs, static_cast<int>(count), offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool non_blocking_write_at1(int d, uint64_t offset,
|
||||
const void* data, std::size_t size,
|
||||
boost::system::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
signed_size_type bytes = ::pwrite(d, data, size, offset);
|
||||
get_last_error(ec, bytes < 0);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
bytes_transferred = bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation failed.
|
||||
bytes_transferred = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_FILE)
|
||||
|
||||
int ioctl(int d, state_type& state, long cmd,
|
||||
ioctl_arg_type* arg, boost::system::error_code& ec)
|
||||
{
|
||||
@@ -331,13 +839,11 @@ int ioctl(int d, state_type& state, long cmd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::ioctl(d, cmd, arg), ec);
|
||||
int result = ::ioctl(d, cmd, arg);
|
||||
get_last_error(ec, result < 0);
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
|
||||
// When updating the non-blocking mode we always perform the ioctl syscall,
|
||||
// even if the flags would otherwise indicate that the descriptor is
|
||||
// already in the correct state. This ensures that the underlying
|
||||
@@ -371,10 +877,8 @@ int fcntl(int d, int cmd, boost::system::error_code& ec)
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::fcntl(d, cmd), ec);
|
||||
if (result != -1)
|
||||
ec = boost::system::error_code();
|
||||
int result = ::fcntl(d, cmd);
|
||||
get_last_error(ec, result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -386,10 +890,8 @@ int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::fcntl(d, cmd, arg), ec);
|
||||
if (result != -1)
|
||||
ec = boost::system::error_code();
|
||||
int result = ::fcntl(d, cmd, arg);
|
||||
get_last_error(ec, result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -406,13 +908,11 @@ int poll_read(int d, state_type state, boost::system::error_code& ec)
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
int timeout = (state & user_set_non_blocking) ? 0 : -1;
|
||||
errno = 0;
|
||||
int result = error_wrapper(::poll(&fds, 1, timeout), ec);
|
||||
int result = ::poll(&fds, 1, timeout);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result == 0)
|
||||
ec = (state & user_set_non_blocking)
|
||||
? boost::asio::error::would_block : boost::system::error_code();
|
||||
else if (result > 0)
|
||||
ec = boost::system::error_code();
|
||||
if (state & user_set_non_blocking)
|
||||
ec = boost::asio::error::would_block;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -429,13 +929,11 @@ int poll_write(int d, state_type state, boost::system::error_code& ec)
|
||||
fds.events = POLLOUT;
|
||||
fds.revents = 0;
|
||||
int timeout = (state & user_set_non_blocking) ? 0 : -1;
|
||||
errno = 0;
|
||||
int result = error_wrapper(::poll(&fds, 1, timeout), ec);
|
||||
int result = ::poll(&fds, 1, timeout);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result == 0)
|
||||
ec = (state & user_set_non_blocking)
|
||||
? boost::asio::error::would_block : boost::system::error_code();
|
||||
else if (result > 0)
|
||||
ec = boost::system::error_code();
|
||||
if (state & user_set_non_blocking)
|
||||
ec = boost::asio::error::would_block;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -452,13 +950,11 @@ int poll_error(int d, state_type state, boost::system::error_code& ec)
|
||||
fds.events = POLLPRI | POLLERR | POLLHUP;
|
||||
fds.revents = 0;
|
||||
int timeout = (state & user_set_non_blocking) ? 0 : -1;
|
||||
errno = 0;
|
||||
int result = error_wrapper(::poll(&fds, 1, timeout), ec);
|
||||
int result = ::poll(&fds, 1, timeout);
|
||||
get_last_error(ec, result < 0);
|
||||
if (result == 0)
|
||||
ec = (state & user_set_non_blocking)
|
||||
? boost::asio::error::would_block : boost::system::error_code();
|
||||
else if (result > 0)
|
||||
ec = boost::system::error_code();
|
||||
if (state & user_set_non_blocking)
|
||||
ec = boost::asio::error::would_block;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,12 +19,20 @@
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_DEV_POLL)
|
||||
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline void dev_poll_reactor::post_immediate_completion(
|
||||
operation* op, bool is_continuation) const
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
@@ -69,6 +77,18 @@ std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& target,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/dev_poll_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <boost/asio/detail/dev_poll_reactor.hpp>
|
||||
#include <boost/asio/detail/assert.hpp>
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
@@ -148,15 +149,24 @@ void dev_poll_reactor::move_descriptor(socket_type,
|
||||
{
|
||||
}
|
||||
|
||||
void dev_poll_reactor::call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self)
|
||||
{
|
||||
static_cast<const dev_poll_reactor*>(self)->post_immediate_completion(
|
||||
op, is_continuation);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
bool is_continuation, bool allow_speculative,
|
||||
void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,7 +179,7 @@ void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
if (op->perform())
|
||||
{
|
||||
lock.unlock();
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -202,6 +212,19 @@ void dev_poll_reactor::cancel_ops(socket_type descriptor,
|
||||
cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::cancel_ops_by_key(socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&,
|
||||
int op_type, void* cancellation_key)
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(
|
||||
descriptor, ops, cancellation_key, boost::asio::error::operation_aborted);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
if (need_interrupt)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
void dev_poll_reactor::deregister_descriptor(socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&, bool)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/epoll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,12 +17,20 @@
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_EPOLL)
|
||||
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline void epoll_reactor::post_immediate_completion(
|
||||
operation* op, bool is_continuation) const
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
@@ -67,6 +75,18 @@ std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& target,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/epoll_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <cstddef>
|
||||
#include <sys/epoll.h>
|
||||
#include <boost/asio/detail/epoll_reactor.hpp>
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
@@ -229,14 +230,23 @@ void epoll_reactor::move_descriptor(socket_type,
|
||||
source_descriptor_data = 0;
|
||||
}
|
||||
|
||||
void epoll_reactor::call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self)
|
||||
{
|
||||
static_cast<const epoll_reactor*>(self)->post_immediate_completion(
|
||||
op, is_continuation);
|
||||
}
|
||||
|
||||
void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
bool is_continuation, bool allow_speculative,
|
||||
void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
{
|
||||
op->ec_ = boost::asio::error::bad_descriptor;
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,7 +254,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
|
||||
if (descriptor_data->shutdown_)
|
||||
{
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -262,7 +272,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
if (descriptor_data->registered_events_ != 0)
|
||||
descriptor_data->try_speculative_[op_type] = false;
|
||||
descriptor_lock.unlock();
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +280,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
if (descriptor_data->registered_events_ == 0)
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_not_supported;
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -289,7 +299,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
{
|
||||
op->ec_ = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -298,7 +308,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
else if (descriptor_data->registered_events_ == 0)
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_not_supported;
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -343,6 +353,35 @@ void epoll_reactor::cancel_ops(socket_type,
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::cancel_ops_by_key(socket_type,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data,
|
||||
int op_type, void* cancellation_key)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
op_queue<operation> ops;
|
||||
op_queue<reactor_op> other_ops;
|
||||
while (reactor_op* op = descriptor_data->op_queue_[op_type].front())
|
||||
{
|
||||
descriptor_data->op_queue_[op_type].pop();
|
||||
if (op->cancellation_key_ == cancellation_key)
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
ops.push(op);
|
||||
}
|
||||
else
|
||||
other_ops.push(op);
|
||||
}
|
||||
descriptor_data->op_queue_[op_type].push(other_ops);
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::deregister_descriptor(socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data, bool closing)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/eventfd_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -23,11 +23,11 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
# include <asm/unistd.h>
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
# include <sys/eventfd.h>
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
#include <boost/asio/detail/cstdint.hpp>
|
||||
#include <boost/asio/detail/eventfd_select_interrupter.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
@@ -46,14 +46,14 @@ eventfd_select_interrupter::eventfd_select_interrupter()
|
||||
|
||||
void eventfd_select_interrupter::open_descriptors()
|
||||
{
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
|
||||
if (read_descriptor_ != -1)
|
||||
{
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
write_descriptor_ = read_descriptor_ =
|
||||
::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
@@ -70,7 +70,7 @@ void eventfd_select_interrupter::open_descriptors()
|
||||
::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
|
||||
if (read_descriptor_ == -1)
|
||||
{
|
||||
@@ -135,8 +135,7 @@ bool eventfd_select_interrupter::reset()
|
||||
int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
return was_interrupted;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -146,12 +145,19 @@ bool eventfd_select_interrupter::reset()
|
||||
// Clear all data from the pipe.
|
||||
char data[1024];
|
||||
int bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
if (bytes_read == sizeof(data))
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
return was_interrupted;
|
||||
if (bytes_read > 0)
|
||||
return true;
|
||||
if (bytes_read == 0)
|
||||
return false;
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EWOULDBLOCK)
|
||||
return true;
|
||||
if (errno == EAGAIN)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/handler_tracking.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -74,11 +74,12 @@ struct handler_tracking::tracking_state
|
||||
static_mutex mutex_;
|
||||
uint64_t next_id_;
|
||||
tss_ptr<completion>* current_completion_;
|
||||
tss_ptr<location>* current_location_;
|
||||
};
|
||||
|
||||
handler_tracking::tracking_state* handler_tracking::get_state()
|
||||
{
|
||||
static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0 };
|
||||
static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0, 0 };
|
||||
return &state;
|
||||
}
|
||||
|
||||
@@ -91,6 +92,25 @@ void handler_tracking::init()
|
||||
static_mutex::scoped_lock lock(state->mutex_);
|
||||
if (state->current_completion_ == 0)
|
||||
state->current_completion_ = new tss_ptr<completion>;
|
||||
if (state->current_location_ == 0)
|
||||
state->current_location_ = new tss_ptr<location>;
|
||||
}
|
||||
|
||||
handler_tracking::location::location(
|
||||
const char* file, int line, const char* func)
|
||||
: file_(file),
|
||||
line_(line),
|
||||
func_(func),
|
||||
next_(*get_state()->current_location_)
|
||||
{
|
||||
if (file_)
|
||||
*get_state()->current_location_ = this;
|
||||
}
|
||||
|
||||
handler_tracking::location::~location()
|
||||
{
|
||||
if (file_)
|
||||
*get_state()->current_location_ = next_;
|
||||
}
|
||||
|
||||
void handler_tracking::creation(execution_context&,
|
||||
@@ -110,6 +130,24 @@ void handler_tracking::creation(execution_context&,
|
||||
if (completion* current_completion = *state->current_completion_)
|
||||
current_id = current_completion->id_;
|
||||
|
||||
for (location* current_location = *state->current_location_;
|
||||
current_location; current_location = current_location->next_)
|
||||
{
|
||||
write_line(
|
||||
#if defined(BOOST_ASIO_WINDOWS)
|
||||
"@asio|%I64u.%06I64u|%I64u^%I64u|%s%s%.80s%s(%.80s:%d)\n",
|
||||
#else // defined(BOOST_ASIO_WINDOWS)
|
||||
"@asio|%llu.%06llu|%llu^%llu|%s%s%.80s%s(%.80s:%d)\n",
|
||||
#endif // defined(BOOST_ASIO_WINDOWS)
|
||||
timestamp.seconds, timestamp.microseconds,
|
||||
current_id, h.id_,
|
||||
current_location == *state->current_location_ ? "in " : "called from ",
|
||||
current_location->func_ ? "'" : "",
|
||||
current_location->func_ ? current_location->func_ : "",
|
||||
current_location->func_ ? "' " : "",
|
||||
current_location->file_, current_location->line_);
|
||||
}
|
||||
|
||||
write_line(
|
||||
#if defined(BOOST_ASIO_WINDOWS)
|
||||
"@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n",
|
||||
@@ -328,7 +366,9 @@ void handler_tracking::write_line(const char* format, ...)
|
||||
va_start(args, format);
|
||||
|
||||
char line[256] = "";
|
||||
#if defined(BOOST_ASIO_HAS_SECURE_RTL)
|
||||
#if defined(BOOST_ASIO_HAS_SNPRINTF)
|
||||
int length = vsnprintf(line, sizeof(line), format, args);
|
||||
#elif defined(BOOST_ASIO_HAS_SECURE_RTL)
|
||||
int length = vsprintf_s(line, sizeof(line), format, args);
|
||||
#else // defined(BOOST_ASIO_HAS_SECURE_RTL)
|
||||
int length = vsprintf(line, format, args);
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// detail/impl/io_uring_descriptor_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/detail/io_uring_descriptor_service.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
io_uring_descriptor_service::io_uring_descriptor_service(
|
||||
execution_context& context)
|
||||
: execution_context_service_base<io_uring_descriptor_service>(context),
|
||||
io_uring_service_(boost::asio::use_service<io_uring_service>(context))
|
||||
{
|
||||
io_uring_service_.init_task();
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::construct(
|
||||
io_uring_descriptor_service::implementation_type& impl)
|
||||
{
|
||||
impl.descriptor_ = -1;
|
||||
impl.state_ = 0;
|
||||
impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::move_construct(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
io_uring_descriptor_service::implementation_type& other_impl)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
impl.descriptor_ = other_impl.descriptor_;
|
||||
other_impl.descriptor_ = -1;
|
||||
|
||||
impl.state_ = other_impl.state_;
|
||||
other_impl.state_ = 0;
|
||||
|
||||
impl.io_object_data_ = other_impl.io_object_data_;
|
||||
other_impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::move_assign(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
io_uring_descriptor_service& /*other_service*/,
|
||||
io_uring_descriptor_service::implementation_type& other_impl)
|
||||
{
|
||||
destroy(impl);
|
||||
|
||||
impl.descriptor_ = other_impl.descriptor_;
|
||||
other_impl.descriptor_ = -1;
|
||||
|
||||
impl.state_ = other_impl.state_;
|
||||
other_impl.state_ = 0;
|
||||
|
||||
impl.io_object_data_ = other_impl.io_object_data_;
|
||||
other_impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::destroy(
|
||||
io_uring_descriptor_service::implementation_type& impl)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"descriptor", &impl, impl.descriptor_, "close"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_descriptor_service::assign(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
const native_handle_type& native_descriptor, boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
io_uring_service_.register_io_object(impl.io_object_data_);
|
||||
|
||||
impl.descriptor_ = native_descriptor;
|
||||
impl.state_ = descriptor_ops::possible_dup;
|
||||
ec = success_ec_;
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_descriptor_service::close(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"descriptor", &impl, impl.descriptor_, "close"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
descriptor_ops::close(impl.descriptor_, impl.state_, ec);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = success_ec_;
|
||||
}
|
||||
|
||||
// The descriptor is closed by the OS even if close() returns an error.
|
||||
//
|
||||
// (Actually, POSIX says the state of the descriptor is unspecified. On
|
||||
// Linux the descriptor is apparently closed anyway; e.g. see
|
||||
// http://lkml.org/lkml/2005/9/10/129
|
||||
construct(impl);
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
io_uring_descriptor_service::native_handle_type
|
||||
io_uring_descriptor_service::release(
|
||||
io_uring_descriptor_service::implementation_type& impl)
|
||||
{
|
||||
native_handle_type descriptor = impl.descriptor_;
|
||||
|
||||
if (is_open(impl))
|
||||
{
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"descriptor", &impl, impl.descriptor_, "release"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
construct(impl);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_descriptor_service::cancel(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"descriptor", &impl, impl.descriptor_, "cancel"));
|
||||
|
||||
io_uring_service_.cancel_ops(impl.io_object_data_);
|
||||
ec = success_ec_;
|
||||
return ec;
|
||||
}
|
||||
|
||||
void io_uring_descriptor_service::start_op(
|
||||
io_uring_descriptor_service::implementation_type& impl,
|
||||
int op_type, io_uring_operation* op, bool is_continuation, bool noop)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
io_uring_service_.start_op(op_type,
|
||||
impl.io_object_data_, op, is_continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
io_uring_service_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP
|
||||
142
linx64/include/boost/asio/detail/impl/io_uring_file_service.ipp
Normal file
142
linx64/include/boost/asio/detail/impl/io_uring_file_service.ipp
Normal file
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// detail/impl/io_uring_file_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_FILE) \
|
||||
&& defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/asio/detail/io_uring_file_service.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
io_uring_file_service::io_uring_file_service(
|
||||
execution_context& context)
|
||||
: execution_context_service_base<io_uring_file_service>(context),
|
||||
descriptor_service_(context)
|
||||
{
|
||||
}
|
||||
|
||||
void io_uring_file_service::shutdown()
|
||||
{
|
||||
descriptor_service_.shutdown();
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_file_service::open(
|
||||
io_uring_file_service::implementation_type& impl,
|
||||
const char* path, file_base::flags open_flags,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
descriptor_ops::state_type state = 0;
|
||||
int fd = descriptor_ops::open(path, static_cast<int>(open_flags), 0777, ec);
|
||||
if (fd < 0)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// We're done. Take ownership of the serial port descriptor.
|
||||
if (descriptor_service_.assign(impl, fd, ec))
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
}
|
||||
|
||||
(void)::posix_fadvise(native_handle(impl), 0, 0,
|
||||
impl.is_stream_ ? POSIX_FADV_SEQUENTIAL : POSIX_FADV_RANDOM);
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
uint64_t io_uring_file_service::size(
|
||||
const io_uring_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec) const
|
||||
{
|
||||
struct stat s;
|
||||
int result = ::fstat(native_handle(impl), &s);
|
||||
descriptor_ops::get_last_error(ec, result != 0);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return !ec ? s.st_size : 0;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_file_service::resize(
|
||||
io_uring_file_service::implementation_type& impl,
|
||||
uint64_t n, boost::system::error_code& ec)
|
||||
{
|
||||
int result = ::ftruncate(native_handle(impl), n);
|
||||
descriptor_ops::get_last_error(ec, result != 0);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_file_service::sync_all(
|
||||
io_uring_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
int result = ::fsync(native_handle(impl));
|
||||
descriptor_ops::get_last_error(ec, result != 0);
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_file_service::sync_data(
|
||||
io_uring_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
#if defined(_POSIX_SYNCHRONIZED_IO)
|
||||
int result = ::fdatasync(native_handle(impl));
|
||||
#else // defined(_POSIX_SYNCHRONIZED_IO)
|
||||
int result = ::fsync(native_handle(impl));
|
||||
#endif // defined(_POSIX_SYNCHRONIZED_IO)
|
||||
descriptor_ops::get_last_error(ec, result != 0);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
uint64_t io_uring_file_service::seek(
|
||||
io_uring_file_service::implementation_type& impl, int64_t offset,
|
||||
file_base::seek_basis whence, boost::system::error_code& ec)
|
||||
{
|
||||
int64_t result = ::lseek(native_handle(impl), offset, whence);
|
||||
descriptor_ops::get_last_error(ec, result < 0);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return !ec ? static_cast<uint64_t>(result) : 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_FILE)
|
||||
// && defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP
|
||||
114
linx64/include/boost/asio/detail/impl/io_uring_service.hpp
Normal file
114
linx64/include/boost/asio/detail/impl/io_uring_service.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// detail/impl/io_uring_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline void io_uring_service::post_immediate_completion(
|
||||
operation* op, bool is_continuation)
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void io_uring_service::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void io_uring_service::remove_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void io_uring_service::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
scheduler_.work_started();
|
||||
if (earliest)
|
||||
{
|
||||
update_timeout();
|
||||
post_submit_sqes_op(lock);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t io_uring_service::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer,
|
||||
std::size_t max_cancelled)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void io_uring_service::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void io_uring_service::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& target,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& source)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer(target, ops);
|
||||
queue.move_timer(target, source);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP
|
||||
916
linx64/include/boost/asio/detail/impl/io_uring_service.ipp
Normal file
916
linx64/include/boost/asio/detail/impl/io_uring_service.ipp
Normal file
@@ -0,0 +1,916 @@
|
||||
//
|
||||
// detail/impl/io_uring_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#include <cstddef>
|
||||
#include <sys/eventfd.h>
|
||||
#include <boost/asio/detail/io_uring_service.hpp>
|
||||
#include <boost/asio/detail/reactor_op.hpp>
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
io_uring_service::io_uring_service(boost::asio::execution_context& ctx)
|
||||
: execution_context_service_base<io_uring_service>(ctx),
|
||||
scheduler_(use_service<scheduler>(ctx)),
|
||||
mutex_(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
|
||||
REACTOR_REGISTRATION, scheduler_.concurrency_hint())),
|
||||
outstanding_work_(0),
|
||||
submit_sqes_op_(this),
|
||||
pending_sqes_(0),
|
||||
pending_submit_sqes_op_(false),
|
||||
shutdown_(false),
|
||||
timeout_(),
|
||||
registration_mutex_(mutex_.enabled()),
|
||||
reactor_(use_service<reactor>(ctx)),
|
||||
reactor_data_(),
|
||||
event_fd_(-1)
|
||||
{
|
||||
reactor_.init_task();
|
||||
init_ring();
|
||||
register_with_reactor();
|
||||
}
|
||||
|
||||
io_uring_service::~io_uring_service()
|
||||
{
|
||||
if (ring_.ring_fd != -1)
|
||||
::io_uring_queue_exit(&ring_);
|
||||
if (event_fd_ != -1)
|
||||
::close(event_fd_);
|
||||
}
|
||||
|
||||
void io_uring_service::shutdown()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
// Cancel all outstanding operations.
|
||||
while (io_object* io_obj = registered_io_objects_.first())
|
||||
{
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
if (!io_obj->queues_[i].op_queue_.empty())
|
||||
{
|
||||
ops.push(io_obj->queues_[i].op_queue_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);
|
||||
}
|
||||
}
|
||||
io_obj->shutdown_ = true;
|
||||
registered_io_objects_.free(io_obj);
|
||||
}
|
||||
|
||||
// Cancel the timeout operation.
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);
|
||||
submit_sqes();
|
||||
|
||||
// Wait for all completions to come back.
|
||||
for (; outstanding_work_ > 0; --outstanding_work_)
|
||||
{
|
||||
::io_uring_cqe* cqe = 0;
|
||||
if (::io_uring_wait_cqe(&ring_, &cqe) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
|
||||
scheduler_.abandon_operations(ops);
|
||||
}
|
||||
|
||||
void io_uring_service::notify_fork(
|
||||
boost::asio::execution_context::fork_event fork_ev)
|
||||
{
|
||||
switch (fork_ev)
|
||||
{
|
||||
case boost::asio::execution_context::fork_prepare:
|
||||
{
|
||||
// Cancel all outstanding operations. They will be restarted
|
||||
// after the fork completes.
|
||||
mutex::scoped_lock registration_lock(registration_mutex_);
|
||||
for (io_object* io_obj = registered_io_objects_.first();
|
||||
io_obj != 0; io_obj = io_obj->next_)
|
||||
{
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
if (!io_obj->queues_[i].op_queue_.empty()
|
||||
&& !io_obj->queues_[i].cancel_requested_)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the timeout operation.
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);
|
||||
submit_sqes();
|
||||
}
|
||||
|
||||
// Wait for all completions to come back, and post all completed I/O
|
||||
// queues to the scheduler. Note that some operations may have already
|
||||
// completed, or were explicitly cancelled. All others will be
|
||||
// automatically restarted.
|
||||
op_queue<operation> ops;
|
||||
for (; outstanding_work_ > 0; --outstanding_work_)
|
||||
{
|
||||
::io_uring_cqe* cqe = 0;
|
||||
if (::io_uring_wait_cqe(&ring_, &cqe) != 0)
|
||||
break;
|
||||
if (void* ptr = ::io_uring_cqe_get_data(cqe))
|
||||
{
|
||||
if (ptr != this && ptr != &timer_queues_ && ptr != &timeout_)
|
||||
{
|
||||
io_queue* io_q = static_cast<io_queue*>(ptr);
|
||||
io_q->set_result(cqe->res);
|
||||
ops.push(io_q);
|
||||
}
|
||||
}
|
||||
}
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
|
||||
// Restart and eventfd operation.
|
||||
register_with_reactor();
|
||||
}
|
||||
break;
|
||||
|
||||
case boost::asio::execution_context::fork_parent:
|
||||
// Restart the timeout and eventfd operations.
|
||||
update_timeout();
|
||||
register_with_reactor();
|
||||
break;
|
||||
|
||||
case boost::asio::execution_context::fork_child:
|
||||
{
|
||||
// The child process gets a new io_uring instance.
|
||||
::io_uring_queue_exit(&ring_);
|
||||
init_ring();
|
||||
register_with_reactor();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::init_task()
|
||||
{
|
||||
scheduler_.init_task();
|
||||
}
|
||||
|
||||
void io_uring_service::register_io_object(
|
||||
io_uring_service::per_io_object_data& io_obj)
|
||||
{
|
||||
io_obj = allocate_io_object();
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
|
||||
io_obj->service_ = this;
|
||||
io_obj->shutdown_ = false;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
io_obj->queues_[i].io_object_ = io_obj;
|
||||
io_obj->queues_[i].cancel_requested_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::register_internal_io_object(
|
||||
io_uring_service::per_io_object_data& io_obj,
|
||||
int op_type, io_uring_operation* op)
|
||||
{
|
||||
io_obj = allocate_io_object();
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
|
||||
io_obj->service_ = this;
|
||||
io_obj->shutdown_ = false;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
io_obj->queues_[i].io_object_ = io_obj;
|
||||
io_obj->queues_[i].cancel_requested_ = false;
|
||||
}
|
||||
|
||||
io_obj->queues_[op_type].op_queue_.push(op);
|
||||
io_object_lock.unlock();
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
op->prepare(sqe);
|
||||
::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);
|
||||
post_submit_sqes_op(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::system::error_code ec(ENOBUFS,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "io_uring_get_sqe");
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::register_buffers(const ::iovec* v, unsigned n)
|
||||
{
|
||||
int result = ::io_uring_register_buffers(&ring_, v, n);
|
||||
if (result < 0)
|
||||
{
|
||||
boost::system::error_code ec(-result,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "io_uring_register_buffers");
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::unregister_buffers()
|
||||
{
|
||||
(void)::io_uring_unregister_buffers(&ring_);
|
||||
}
|
||||
|
||||
void io_uring_service::start_op(int op_type,
|
||||
io_uring_service::per_io_object_data& io_obj,
|
||||
io_uring_operation* op, bool is_continuation)
|
||||
{
|
||||
if (!io_obj)
|
||||
{
|
||||
op->ec_ = boost::asio::error::bad_descriptor;
|
||||
post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
|
||||
if (io_obj->shutdown_)
|
||||
{
|
||||
io_object_lock.unlock();
|
||||
post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (io_obj->queues_[op_type].op_queue_.empty())
|
||||
{
|
||||
if (op->perform(false))
|
||||
{
|
||||
io_object_lock.unlock();
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
io_obj->queues_[op_type].op_queue_.push(op);
|
||||
io_object_lock.unlock();
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
op->prepare(sqe);
|
||||
::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);
|
||||
scheduler_.work_started();
|
||||
post_submit_sqes_op(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock.unlock();
|
||||
io_obj->queues_[op_type].set_result(-ENOBUFS);
|
||||
post_immediate_completion(&io_obj->queues_[op_type], is_continuation);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
io_obj->queues_[op_type].op_queue_.push(op);
|
||||
scheduler_.work_started();
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::cancel_ops(io_uring_service::per_io_object_data& io_obj)
|
||||
{
|
||||
if (!io_obj)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
op_queue<operation> ops;
|
||||
do_cancel_ops(io_obj, ops);
|
||||
io_object_lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void io_uring_service::cancel_ops_by_key(
|
||||
io_uring_service::per_io_object_data& io_obj,
|
||||
int op_type, void* cancellation_key)
|
||||
{
|
||||
if (!io_obj)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
|
||||
bool first = true;
|
||||
op_queue<operation> ops;
|
||||
op_queue<io_uring_operation> other_ops;
|
||||
while (io_uring_operation* op = io_obj->queues_[op_type].op_queue_.front())
|
||||
{
|
||||
io_obj->queues_[op_type].op_queue_.pop();
|
||||
if (op->cancellation_key_ == cancellation_key)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
other_ops.push(op);
|
||||
if (!io_obj->queues_[op_type].cancel_requested_)
|
||||
{
|
||||
io_obj->queues_[op_type].cancel_requested_ = true;
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
::io_uring_prep_cancel(sqe, &io_obj->queues_[op_type], 0);
|
||||
submit_sqes();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
else
|
||||
other_ops.push(op);
|
||||
first = false;
|
||||
}
|
||||
io_obj->queues_[op_type].op_queue_.push(other_ops);
|
||||
|
||||
io_object_lock.unlock();
|
||||
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void io_uring_service::deregister_io_object(
|
||||
io_uring_service::per_io_object_data& io_obj)
|
||||
{
|
||||
if (!io_obj)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock io_object_lock(io_obj->mutex_);
|
||||
if (!io_obj->shutdown_)
|
||||
{
|
||||
op_queue<operation> ops;
|
||||
bool pending_cancelled_ops = do_cancel_ops(io_obj, ops);
|
||||
io_obj->shutdown_ = true;
|
||||
io_object_lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
if (pending_cancelled_ops)
|
||||
{
|
||||
// There are still pending operations. Prevent cleanup_io_object from
|
||||
// freeing the I/O object and let the last operation to complete free it.
|
||||
io_obj = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Leave io_obj set so that it will be freed by the subsequent call to
|
||||
// cleanup_io_object.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are shutting down, so prevent cleanup_io_object from freeing
|
||||
// the I/O object and let the destructor free it instead.
|
||||
io_obj = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::cleanup_io_object(
|
||||
io_uring_service::per_io_object_data& io_obj)
|
||||
{
|
||||
if (io_obj)
|
||||
{
|
||||
free_io_object(io_obj);
|
||||
io_obj = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::run(long usec, op_queue<operation>& ops)
|
||||
{
|
||||
__kernel_timespec ts;
|
||||
int local_ops = 0;
|
||||
|
||||
if (usec > 0)
|
||||
{
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = (usec % 1000000) * 1000;
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
++local_ops;
|
||||
::io_uring_prep_timeout(sqe, &ts, 0, 0);
|
||||
::io_uring_sqe_set_data(sqe, &ts);
|
||||
submit_sqes();
|
||||
}
|
||||
}
|
||||
|
||||
::io_uring_cqe* cqe = 0;
|
||||
int result = (usec == 0)
|
||||
? ::io_uring_peek_cqe(&ring_, &cqe)
|
||||
: ::io_uring_wait_cqe(&ring_, &cqe);
|
||||
|
||||
if (local_ops > 0)
|
||||
{
|
||||
if (result != 0 || ::io_uring_cqe_get_data(cqe) != &ts)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
++local_ops;
|
||||
::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&ts), 0);
|
||||
::io_uring_sqe_set_data(sqe, &ts);
|
||||
submit_sqes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check_timers = false;
|
||||
int count = 0;
|
||||
while (result == 0 || local_ops > 0)
|
||||
{
|
||||
if (result == 0)
|
||||
{
|
||||
if (void* ptr = ::io_uring_cqe_get_data(cqe))
|
||||
{
|
||||
if (ptr == this)
|
||||
{
|
||||
// The io_uring service was interrupted.
|
||||
}
|
||||
else if (ptr == &timer_queues_)
|
||||
{
|
||||
check_timers = true;
|
||||
}
|
||||
else if (ptr == &timeout_)
|
||||
{
|
||||
check_timers = true;
|
||||
timeout_.tv_sec = 0;
|
||||
timeout_.tv_nsec = 0;
|
||||
}
|
||||
else if (ptr == &ts)
|
||||
{
|
||||
--local_ops;
|
||||
}
|
||||
else
|
||||
{
|
||||
io_queue* io_q = static_cast<io_queue*>(ptr);
|
||||
io_q->set_result(cqe->res);
|
||||
ops.push(io_q);
|
||||
}
|
||||
}
|
||||
::io_uring_cqe_seen(&ring_, cqe);
|
||||
++count;
|
||||
}
|
||||
result = (count < complete_batch_size || local_ops > 0)
|
||||
? ::io_uring_peek_cqe(&ring_, &cqe) : -EAGAIN;
|
||||
}
|
||||
|
||||
decrement(outstanding_work_, count);
|
||||
|
||||
if (check_timers)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
if (timeout_.tv_sec == 0 && timeout_.tv_nsec == 0)
|
||||
{
|
||||
timeout_ = get_timeout();
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
::io_uring_prep_timeout(sqe, &timeout_, 0, 0);
|
||||
::io_uring_sqe_set_data(sqe, &timeout_);
|
||||
push_submit_sqes_op(ops);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::interrupt()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
::io_uring_prep_nop(sqe);
|
||||
::io_uring_sqe_set_data(sqe, this);
|
||||
}
|
||||
submit_sqes();
|
||||
}
|
||||
|
||||
void io_uring_service::init_ring()
|
||||
{
|
||||
int result = ::io_uring_queue_init(ring_size, &ring_, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
ring_.ring_fd = -1;
|
||||
boost::system::error_code ec(-result,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "io_uring_queue_init");
|
||||
}
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
event_fd_ = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
if (event_fd_ < 0)
|
||||
{
|
||||
boost::system::error_code ec(-result,
|
||||
boost::asio::error::get_system_category());
|
||||
::io_uring_queue_exit(&ring_);
|
||||
boost::asio::detail::throw_error(ec, "eventfd");
|
||||
}
|
||||
|
||||
result = ::io_uring_register_eventfd(&ring_, event_fd_);
|
||||
if (result < 0)
|
||||
{
|
||||
::close(event_fd_);
|
||||
::io_uring_queue_exit(&ring_);
|
||||
boost::system::error_code ec(-result,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "io_uring_queue_init");
|
||||
}
|
||||
#endif // !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
class io_uring_service::event_fd_read_op :
|
||||
public reactor_op
|
||||
{
|
||||
public:
|
||||
event_fd_read_op(io_uring_service* s)
|
||||
: reactor_op(boost::system::error_code(),
|
||||
&event_fd_read_op::do_perform, event_fd_read_op::do_complete),
|
||||
service_(s)
|
||||
{
|
||||
}
|
||||
|
||||
static status do_perform(reactor_op* base)
|
||||
{
|
||||
event_fd_read_op* o(static_cast<event_fd_read_op*>(base));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Only perform one read. The kernel maintains an atomic counter.
|
||||
uint64_t counter(0);
|
||||
errno = 0;
|
||||
int bytes_read = ::read(o->service_->event_fd_,
|
||||
&counter, sizeof(uint64_t));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
op_queue<operation> ops;
|
||||
o->service_->run(0, ops);
|
||||
o->service_->scheduler_.post_deferred_completions(ops);
|
||||
|
||||
return not_done;
|
||||
}
|
||||
|
||||
static void do_complete(void* /*owner*/, operation* base,
|
||||
const boost::system::error_code& /*ec*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
event_fd_read_op* o(static_cast<event_fd_read_op*>(base));
|
||||
delete o;
|
||||
}
|
||||
|
||||
private:
|
||||
io_uring_service* service_;
|
||||
};
|
||||
#endif // !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
void io_uring_service::register_with_reactor()
|
||||
{
|
||||
#if !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_.register_internal_descriptor(reactor::read_op,
|
||||
event_fd_, reactor_data_, new event_fd_read_op(this));
|
||||
#endif // !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
|
||||
io_uring_service::io_object* io_uring_service::allocate_io_object()
|
||||
{
|
||||
mutex::scoped_lock registration_lock(registration_mutex_);
|
||||
return registered_io_objects_.alloc(
|
||||
BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
|
||||
REACTOR_IO, scheduler_.concurrency_hint()));
|
||||
}
|
||||
|
||||
void io_uring_service::free_io_object(io_uring_service::io_object* io_obj)
|
||||
{
|
||||
mutex::scoped_lock registration_lock(registration_mutex_);
|
||||
registered_io_objects_.free(io_obj);
|
||||
}
|
||||
|
||||
bool io_uring_service::do_cancel_ops(
|
||||
per_io_object_data& io_obj, op_queue<operation>& ops)
|
||||
{
|
||||
bool cancel_op = false;
|
||||
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
if (io_uring_operation* first_op = io_obj->queues_[i].op_queue_.front())
|
||||
{
|
||||
cancel_op = true;
|
||||
io_obj->queues_[i].op_queue_.pop();
|
||||
while (io_uring_operation* op = io_obj->queues_[i].op_queue_.front())
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
io_obj->queues_[i].op_queue_.pop();
|
||||
ops.push(op);
|
||||
}
|
||||
io_obj->queues_[i].op_queue_.push(first_op);
|
||||
}
|
||||
}
|
||||
|
||||
if (cancel_op)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
if (!io_obj->queues_[i].op_queue_.empty()
|
||||
&& !io_obj->queues_[i].cancel_requested_)
|
||||
{
|
||||
io_obj->queues_[i].cancel_requested_ = true;
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);
|
||||
}
|
||||
}
|
||||
submit_sqes();
|
||||
}
|
||||
|
||||
return cancel_op;
|
||||
}
|
||||
|
||||
void io_uring_service::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void io_uring_service::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
void io_uring_service::update_timeout()
|
||||
{
|
||||
if (::io_uring_sqe* sqe = get_sqe())
|
||||
{
|
||||
::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&timeout_), 0);
|
||||
::io_uring_sqe_set_data(sqe, &timer_queues_);
|
||||
}
|
||||
}
|
||||
|
||||
__kernel_timespec io_uring_service::get_timeout() const
|
||||
{
|
||||
__kernel_timespec ts;
|
||||
long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
|
||||
return ts;
|
||||
}
|
||||
|
||||
::io_uring_sqe* io_uring_service::get_sqe()
|
||||
{
|
||||
::io_uring_sqe* sqe = ::io_uring_get_sqe(&ring_);
|
||||
if (!sqe)
|
||||
{
|
||||
submit_sqes();
|
||||
sqe = ::io_uring_get_sqe(&ring_);
|
||||
}
|
||||
if (sqe)
|
||||
{
|
||||
::io_uring_sqe_set_data(sqe, 0);
|
||||
++pending_sqes_;
|
||||
}
|
||||
return sqe;
|
||||
}
|
||||
|
||||
void io_uring_service::submit_sqes()
|
||||
{
|
||||
if (pending_sqes_ != 0)
|
||||
{
|
||||
int result = ::io_uring_submit(&ring_);
|
||||
if (result > 0)
|
||||
{
|
||||
pending_sqes_ -= result;
|
||||
increment(outstanding_work_, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::post_submit_sqes_op(mutex::scoped_lock& lock)
|
||||
{
|
||||
if (pending_sqes_ >= submit_batch_size)
|
||||
{
|
||||
submit_sqes();
|
||||
}
|
||||
else if (pending_sqes_ != 0 && !pending_submit_sqes_op_)
|
||||
{
|
||||
pending_submit_sqes_op_ = true;
|
||||
lock.unlock();
|
||||
scheduler_.post_immediate_completion(&submit_sqes_op_, false);
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_service::push_submit_sqes_op(op_queue<operation>& ops)
|
||||
{
|
||||
if (pending_sqes_ != 0 && !pending_submit_sqes_op_)
|
||||
{
|
||||
pending_submit_sqes_op_ = true;
|
||||
ops.push(&submit_sqes_op_);
|
||||
scheduler_.compensating_work_started();
|
||||
}
|
||||
}
|
||||
|
||||
io_uring_service::submit_sqes_op::submit_sqes_op(io_uring_service* s)
|
||||
: operation(&io_uring_service::submit_sqes_op::do_complete),
|
||||
service_(s)
|
||||
{
|
||||
}
|
||||
|
||||
void io_uring_service::submit_sqes_op::do_complete(void* owner, operation* base,
|
||||
const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
if (owner)
|
||||
{
|
||||
submit_sqes_op* o = static_cast<submit_sqes_op*>(base);
|
||||
mutex::scoped_lock lock(o->service_->mutex_);
|
||||
o->service_->submit_sqes();
|
||||
if (o->service_->pending_sqes_ != 0)
|
||||
o->service_->scheduler_.post_immediate_completion(o, true);
|
||||
else
|
||||
o->service_->pending_submit_sqes_op_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
io_uring_service::io_queue::io_queue()
|
||||
: operation(&io_uring_service::io_queue::do_complete)
|
||||
{
|
||||
}
|
||||
|
||||
struct io_uring_service::perform_io_cleanup_on_block_exit
|
||||
{
|
||||
explicit perform_io_cleanup_on_block_exit(io_uring_service* s)
|
||||
: service_(s), io_object_to_free_(0), first_op_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~perform_io_cleanup_on_block_exit()
|
||||
{
|
||||
if (io_object_to_free_)
|
||||
{
|
||||
mutex::scoped_lock lock(service_->mutex_);
|
||||
service_->free_io_object(io_object_to_free_);
|
||||
}
|
||||
|
||||
if (first_op_)
|
||||
{
|
||||
// Post the remaining completed operations for invocation.
|
||||
if (!ops_.empty())
|
||||
service_->scheduler_.post_deferred_completions(ops_);
|
||||
|
||||
// A user-initiated operation has completed, but there's no need to
|
||||
// explicitly call work_finished() here. Instead, we'll take advantage of
|
||||
// the fact that the scheduler will call work_finished() once we return.
|
||||
}
|
||||
else
|
||||
{
|
||||
// No user-initiated operations have completed, so we need to compensate
|
||||
// for the work_finished() call that the scheduler will make once this
|
||||
// operation returns.
|
||||
service_->scheduler_.compensating_work_started();
|
||||
}
|
||||
}
|
||||
|
||||
io_uring_service* service_;
|
||||
io_object* io_object_to_free_;
|
||||
op_queue<operation> ops_;
|
||||
operation* first_op_;
|
||||
};
|
||||
|
||||
operation* io_uring_service::io_queue::perform_io(int result)
|
||||
{
|
||||
perform_io_cleanup_on_block_exit io_cleanup(io_object_->service_);
|
||||
mutex::scoped_lock io_object_lock(io_object_->mutex_);
|
||||
|
||||
if (result != -ECANCELED || cancel_requested_)
|
||||
{
|
||||
if (io_uring_operation* op = op_queue_.front())
|
||||
{
|
||||
if (result < 0)
|
||||
{
|
||||
op->ec_.assign(-result, boost::asio::error::get_system_category());
|
||||
op->bytes_transferred_ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_.assign(0, op->ec_.category());
|
||||
op->bytes_transferred_ = static_cast<std::size_t>(result);
|
||||
}
|
||||
}
|
||||
|
||||
while (io_uring_operation* op = op_queue_.front())
|
||||
{
|
||||
if (op->perform(io_cleanup.ops_.empty()))
|
||||
{
|
||||
op_queue_.pop();
|
||||
io_cleanup.ops_.push(op);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cancel_requested_ = false;
|
||||
|
||||
if (!op_queue_.empty())
|
||||
{
|
||||
io_uring_service* service = io_object_->service_;
|
||||
mutex::scoped_lock lock(service->mutex_);
|
||||
if (::io_uring_sqe* sqe = service->get_sqe())
|
||||
{
|
||||
op_queue_.front()->prepare(sqe);
|
||||
::io_uring_sqe_set_data(sqe, this);
|
||||
service->post_submit_sqes_op(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock.unlock();
|
||||
while (io_uring_operation* op = op_queue_.front())
|
||||
{
|
||||
op->ec_ = boost::asio::error::no_buffer_space;
|
||||
op_queue_.pop();
|
||||
io_cleanup.ops_.push(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The last operation to complete on a shut down object must free it.
|
||||
if (io_object_->shutdown_)
|
||||
{
|
||||
io_cleanup.io_object_to_free_ = io_object_;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
if (!io_object_->queues_[i].op_queue_.empty())
|
||||
io_cleanup.io_object_to_free_ = 0;
|
||||
}
|
||||
|
||||
// The first operation will be returned for completion now. The others will
|
||||
// be posted for later by the io_cleanup object's destructor.
|
||||
io_cleanup.first_op_ = io_cleanup.ops_.front();
|
||||
io_cleanup.ops_.pop();
|
||||
return io_cleanup.first_op_;
|
||||
}
|
||||
|
||||
void io_uring_service::io_queue::do_complete(void* owner, operation* base,
|
||||
const boost::system::error_code& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (owner)
|
||||
{
|
||||
io_queue* io_q = static_cast<io_queue*>(base);
|
||||
int result = static_cast<int>(bytes_transferred);
|
||||
if (operation* op = io_q->perform_io(result))
|
||||
{
|
||||
op->complete(owner, ec, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io_uring_service::io_object::io_object(bool locking)
|
||||
: mutex_(locking)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP
|
||||
@@ -0,0 +1,251 @@
|
||||
//
|
||||
// detail/io_uring_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#include <boost/asio/detail/io_uring_socket_service_base.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
io_uring_socket_service_base::io_uring_socket_service_base(
|
||||
execution_context& context)
|
||||
: io_uring_service_(boost::asio::use_service<io_uring_service>(context))
|
||||
{
|
||||
io_uring_service_.init_task();
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::base_shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::construct(
|
||||
io_uring_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::base_move_construct(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
io_uring_socket_service_base::base_implementation_type& other_impl)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
impl.socket_ = other_impl.socket_;
|
||||
other_impl.socket_ = invalid_socket;
|
||||
|
||||
impl.state_ = other_impl.state_;
|
||||
other_impl.state_ = 0;
|
||||
|
||||
impl.io_object_data_ = other_impl.io_object_data_;
|
||||
other_impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::base_move_assign(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
io_uring_socket_service_base& /*other_service*/,
|
||||
io_uring_socket_service_base::base_implementation_type& other_impl)
|
||||
{
|
||||
destroy(impl);
|
||||
|
||||
impl.socket_ = other_impl.socket_;
|
||||
other_impl.socket_ = invalid_socket;
|
||||
|
||||
impl.state_ = other_impl.state_;
|
||||
other_impl.state_ = 0;
|
||||
|
||||
impl.io_object_data_ = other_impl.io_object_data_;
|
||||
other_impl.io_object_data_ = 0;
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::destroy(
|
||||
io_uring_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
if (impl.socket_ != invalid_socket)
|
||||
{
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"socket", &impl, impl.socket_, "close"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
boost::system::error_code ignored_ec;
|
||||
socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_socket_service_base::close(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"socket", &impl, impl.socket_, "close"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
socket_ops::close(impl.socket_, impl.state_, false, ec);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = success_ec_;
|
||||
}
|
||||
|
||||
// The descriptor is closed by the OS even if close() returns an error.
|
||||
//
|
||||
// (Actually, POSIX says the state of the descriptor is unspecified. On
|
||||
// Linux the descriptor is apparently closed anyway; e.g. see
|
||||
// http://lkml.org/lkml/2005/9/10/129
|
||||
construct(impl);
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
socket_type io_uring_socket_service_base::release(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return invalid_socket;
|
||||
}
|
||||
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"socket", &impl, impl.socket_, "release"));
|
||||
|
||||
io_uring_service_.deregister_io_object(impl.io_object_data_);
|
||||
io_uring_service_.cleanup_io_object(impl.io_object_data_);
|
||||
socket_type sock = impl.socket_;
|
||||
construct(impl);
|
||||
ec = success_ec_;
|
||||
return sock;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_socket_service_base::cancel(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
return ec;
|
||||
}
|
||||
|
||||
BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
|
||||
"socket", &impl, impl.socket_, "cancel"));
|
||||
|
||||
io_uring_service_.cancel_ops(impl.io_object_data_);
|
||||
ec = success_ec_;
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_socket_service_base::do_open(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
int af, int type, int protocol, boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
socket_holder sock(socket_ops::socket(af, type, protocol, ec));
|
||||
if (sock.get() == invalid_socket)
|
||||
return ec;
|
||||
|
||||
io_uring_service_.register_io_object(impl.io_object_data_);
|
||||
|
||||
impl.socket_ = sock.release();
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
ec = success_ec_;
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code io_uring_socket_service_base::do_assign(
|
||||
io_uring_socket_service_base::base_implementation_type& impl, int type,
|
||||
const io_uring_socket_service_base::native_handle_type& native_socket,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
io_uring_service_.register_io_object(impl.io_object_data_);
|
||||
|
||||
impl.socket_ = native_socket;
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
impl.state_ |= socket_ops::possible_dup;
|
||||
ec = success_ec_;
|
||||
return ec;
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::start_op(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
int op_type, io_uring_operation* op, bool is_continuation, bool noop)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
io_uring_service_.start_op(op_type,
|
||||
impl.io_object_data_, op, is_continuation);
|
||||
}
|
||||
else
|
||||
{
|
||||
io_uring_service_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
void io_uring_socket_service_base::start_accept_op(
|
||||
io_uring_socket_service_base::base_implementation_type& impl,
|
||||
io_uring_operation* op, bool is_continuation, bool peer_is_open)
|
||||
{
|
||||
if (!peer_is_open)
|
||||
start_op(impl, io_uring_service::read_op, op, is_continuation, false);
|
||||
else
|
||||
{
|
||||
op->ec_ = boost::asio::error::already_open;
|
||||
io_uring_service_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/kqueue_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -20,12 +20,20 @@
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_KQUEUE)
|
||||
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline void kqueue_reactor::post_immediate_completion(
|
||||
operation* op, bool is_continuation) const
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
@@ -71,6 +79,18 @@ std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& target,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/kqueue_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -25,9 +25,13 @@
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#if defined(__NetBSD__) && __NetBSD_Version__ < 999001500
|
||||
# define BOOST_ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
|
||||
EV_SET(ev, ident, filt, flags, fflags, data, \
|
||||
reinterpret_cast<intptr_t>(static_cast<void*>(udata)))
|
||||
@@ -187,14 +191,23 @@ void kqueue_reactor::move_descriptor(socket_type,
|
||||
source_descriptor_data = 0;
|
||||
}
|
||||
|
||||
void kqueue_reactor::call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self)
|
||||
{
|
||||
static_cast<const kqueue_reactor*>(self)->post_immediate_completion(
|
||||
op, is_continuation);
|
||||
}
|
||||
|
||||
void kqueue_reactor::start_op(int op_type, socket_type descriptor,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
bool is_continuation, bool allow_speculative,
|
||||
void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
{
|
||||
op->ec_ = boost::asio::error::bad_descriptor;
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -202,7 +215,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
|
||||
|
||||
if (descriptor_data->shutdown_)
|
||||
{
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,7 +230,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_lock.unlock();
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -236,7 +249,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
|
||||
{
|
||||
op->ec_ = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -283,6 +296,35 @@ void kqueue_reactor::cancel_ops(socket_type,
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void kqueue_reactor::cancel_ops_by_key(socket_type,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data,
|
||||
int op_type, void* cancellation_key)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
op_queue<operation> ops;
|
||||
op_queue<reactor_op> other_ops;
|
||||
while (reactor_op* op = descriptor_data->op_queue_[op_type].front())
|
||||
{
|
||||
descriptor_data->op_queue_[op_type].pop();
|
||||
if (op->cancellation_key_ == cancellation_key)
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
ops.push(op);
|
||||
}
|
||||
else
|
||||
other_ops.push(op);
|
||||
}
|
||||
descriptor_data->op_queue_[op_type].push(other_ops);
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void kqueue_reactor::deregister_descriptor(socket_type descriptor,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data, bool closing)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/null_event.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/pipe_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -102,12 +102,17 @@ bool pipe_select_interrupter::reset()
|
||||
{
|
||||
char data[1024];
|
||||
signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
if (bytes_read == sizeof(data))
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
return was_interrupted;
|
||||
if (bytes_read > 0)
|
||||
return true;
|
||||
if (bytes_read == 0)
|
||||
return false;
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/posix_event.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -38,10 +38,14 @@ posix_event::posix_event()
|
||||
#else // (defined(__MACH__) && defined(__APPLE__))
|
||||
// || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
|
||||
::pthread_condattr_t attr;
|
||||
::pthread_condattr_init(&attr);
|
||||
int error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
int error = ::pthread_condattr_init(&attr);
|
||||
if (error == 0)
|
||||
error = ::pthread_cond_init(&cond_, &attr);
|
||||
{
|
||||
error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
if (error == 0)
|
||||
error = ::pthread_cond_init(&cond_, &attr);
|
||||
::pthread_condattr_destroy(&attr);
|
||||
}
|
||||
#endif // (defined(__MACH__) && defined(__APPLE__))
|
||||
// || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/posix_mutex.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
//
|
||||
// detail/impl/reactive_serial_port_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// detail/impl/posix_serial_port_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
@@ -22,7 +22,7 @@
|
||||
#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <cstring>
|
||||
#include <boost/asio/detail/reactive_serial_port_service.hpp>
|
||||
#include <boost/asio/detail/posix_serial_port_service.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -30,25 +30,26 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_serial_port_service::reactive_serial_port_service(
|
||||
posix_serial_port_service::posix_serial_port_service(
|
||||
execution_context& context)
|
||||
: execution_context_service_base<reactive_serial_port_service>(context),
|
||||
: execution_context_service_base<posix_serial_port_service>(context),
|
||||
descriptor_service_(context)
|
||||
{
|
||||
}
|
||||
|
||||
void reactive_serial_port_service::shutdown()
|
||||
void posix_serial_port_service::shutdown()
|
||||
{
|
||||
descriptor_service_.shutdown();
|
||||
}
|
||||
|
||||
boost::system::error_code reactive_serial_port_service::open(
|
||||
reactive_serial_port_service::implementation_type& impl,
|
||||
boost::system::error_code posix_serial_port_service::open(
|
||||
posix_serial_port_service::implementation_type& impl,
|
||||
const std::string& device, boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -56,7 +57,10 @@ boost::system::error_code reactive_serial_port_service::open(
|
||||
int fd = descriptor_ops::open(device.c_str(),
|
||||
O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
|
||||
if (fd < 0)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
|
||||
if (s >= 0)
|
||||
@@ -65,13 +69,14 @@ boost::system::error_code reactive_serial_port_service::open(
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set up default serial port options.
|
||||
termios ios;
|
||||
errno = 0;
|
||||
s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
|
||||
s = ::tcgetattr(fd, &ios);
|
||||
descriptor_ops::get_last_error(ec, s < 0);
|
||||
if (s >= 0)
|
||||
{
|
||||
#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
|
||||
@@ -86,13 +91,14 @@ boost::system::error_code reactive_serial_port_service::open(
|
||||
#endif
|
||||
ios.c_iflag |= IGNPAR;
|
||||
ios.c_cflag |= CREAD | CLOCAL;
|
||||
errno = 0;
|
||||
s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
|
||||
s = ::tcsetattr(fd, TCSANOW, &ios);
|
||||
descriptor_ops::get_last_error(ec, s < 0);
|
||||
}
|
||||
if (s < 0)
|
||||
{
|
||||
boost::system::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -103,43 +109,53 @@ boost::system::error_code reactive_serial_port_service::open(
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
}
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code reactive_serial_port_service::do_set_option(
|
||||
reactive_serial_port_service::implementation_type& impl,
|
||||
reactive_serial_port_service::store_function_type store,
|
||||
boost::system::error_code posix_serial_port_service::do_set_option(
|
||||
posix_serial_port_service::implementation_type& impl,
|
||||
posix_serial_port_service::store_function_type store,
|
||||
const void* option, boost::system::error_code& ec)
|
||||
{
|
||||
termios ios;
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native_handle(impl), &ios), ec);
|
||||
if (ec)
|
||||
int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);
|
||||
descriptor_ops::get_last_error(ec, s < 0);
|
||||
if (s < 0)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (store(option, ios, ec))
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcsetattr(
|
||||
descriptor_service_.native_handle(impl), TCSANOW, &ios), ec);
|
||||
s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios);
|
||||
descriptor_ops::get_last_error(ec, s < 0);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
boost::system::error_code reactive_serial_port_service::do_get_option(
|
||||
const reactive_serial_port_service::implementation_type& impl,
|
||||
reactive_serial_port_service::load_function_type load,
|
||||
boost::system::error_code posix_serial_port_service::do_get_option(
|
||||
const posix_serial_port_service::implementation_type& impl,
|
||||
posix_serial_port_service::load_function_type load,
|
||||
void* option, boost::system::error_code& ec) const
|
||||
{
|
||||
termios ios;
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native_handle(impl), &ios), ec);
|
||||
if (ec)
|
||||
int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);
|
||||
descriptor_ops::get_last_error(ec, s < 0);
|
||||
if (s < 0)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
return load(option, ios, ec);
|
||||
load(option, ios, ec);
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -151,4 +167,4 @@ boost::system::error_code reactive_serial_port_service::do_get_option(
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
|
||||
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/posix_thread.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/posix_tss_ptr.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/reactive_descriptor_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
#if !defined(BOOST_ASIO_WINDOWS) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(__CYGWIN__)
|
||||
&& !defined(__CYGWIN__) \
|
||||
&& !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/detail/reactive_descriptor_service.hpp>
|
||||
@@ -47,11 +48,13 @@ void reactive_descriptor_service::construct(
|
||||
{
|
||||
impl.descriptor_ = -1;
|
||||
impl.state_ = 0;
|
||||
impl.reactor_data_ = reactor::per_descriptor_data();
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::move_construct(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
reactive_descriptor_service::implementation_type& other_impl)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
impl.descriptor_ = other_impl.descriptor_;
|
||||
other_impl.descriptor_ = -1;
|
||||
@@ -105,6 +108,7 @@ boost::system::error_code reactive_descriptor_service::assign(
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -113,6 +117,7 @@ boost::system::error_code reactive_descriptor_service::assign(
|
||||
{
|
||||
ec = boost::system::error_code(err,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -151,6 +156,7 @@ boost::system::error_code reactive_descriptor_service::close(
|
||||
// We'll just have to assume that other OSes follow the same behaviour.)
|
||||
construct(impl);
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -180,6 +186,7 @@ boost::system::error_code reactive_descriptor_service::cancel(
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -191,10 +198,10 @@ boost::system::error_code reactive_descriptor_service::cancel(
|
||||
return ec;
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::start_op(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
int op_type, reactor_op* op, bool is_continuation,
|
||||
bool is_non_blocking, bool noop)
|
||||
void reactive_descriptor_service::do_start_op(implementation_type& impl,
|
||||
int op_type, reactor_op* op, bool is_continuation, bool is_non_blocking,
|
||||
bool noop, void (*on_immediate)(operation* op, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
@@ -202,13 +209,13 @@ void reactive_descriptor_service::start_op(
|
||||
descriptor_ops::set_internal_non_blocking(
|
||||
impl.descriptor_, impl.state_, true, op->ec_))
|
||||
{
|
||||
reactor_.start_op(op_type, impl.descriptor_,
|
||||
impl.reactor_data_, op, is_continuation, is_non_blocking);
|
||||
reactor_.start_op(op_type, impl.descriptor_, impl.reactor_data_, op,
|
||||
is_continuation, is_non_blocking, on_immediate, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -220,5 +227,6 @@ void reactive_descriptor_service::start_op(
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
// && !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/reactive_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -18,7 +18,8 @@
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_IOCP) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#include <boost/asio/detail/reactive_socket_service_base.hpp>
|
||||
|
||||
@@ -44,11 +45,13 @@ void reactive_socket_service_base::construct(
|
||||
{
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
impl.reactor_data_ = reactor::per_descriptor_data();
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::base_move_construct(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
reactive_socket_service_base::base_implementation_type& other_impl)
|
||||
BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
impl.socket_ = other_impl.socket_;
|
||||
other_impl.socket_ = invalid_socket;
|
||||
@@ -231,10 +234,11 @@ boost::system::error_code reactive_socket_service_base::do_assign(
|
||||
return ec;
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
int op_type, reactor_op* op, bool is_continuation,
|
||||
bool is_non_blocking, bool noop)
|
||||
void reactive_socket_service_base::do_start_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl, int op_type,
|
||||
reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,
|
||||
void (*on_immediate)(operation* op, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
@@ -242,32 +246,38 @@ void reactive_socket_service_base::start_op(
|
||||
|| socket_ops::set_internal_non_blocking(
|
||||
impl.socket_, impl.state_, true, op->ec_))
|
||||
{
|
||||
reactor_.start_op(op_type, impl.socket_,
|
||||
impl.reactor_data_, op, is_continuation, is_non_blocking);
|
||||
reactor_.start_op(op_type, impl.socket_, impl.reactor_data_, op,
|
||||
is_continuation, is_non_blocking, on_immediate, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_accept_op(
|
||||
void reactive_socket_service_base::do_start_accept_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
reactor_op* op, bool is_continuation, bool peer_is_open)
|
||||
reactor_op* op, bool is_continuation, bool peer_is_open,
|
||||
void (*on_immediate)(operation* op, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if (!peer_is_open)
|
||||
start_op(impl, reactor::read_op, op, is_continuation, true, false);
|
||||
{
|
||||
do_start_op(impl, reactor::read_op, op, is_continuation,
|
||||
true, false, on_immediate, immediate_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = boost::asio::error::already_open;
|
||||
reactor_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
}
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_connect_op(
|
||||
void reactive_socket_service_base::do_start_connect_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
reactor_op* op, bool is_continuation,
|
||||
const socket_addr_type* addr, size_t addrlen)
|
||||
reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,
|
||||
void (*on_immediate)(operation* op, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
if ((impl.state_ & socket_ops::non_blocking)
|
||||
|| socket_ops::set_internal_non_blocking(
|
||||
@@ -279,14 +289,14 @@ void reactive_socket_service_base::start_connect_op(
|
||||
|| op->ec_ == boost::asio::error::would_block)
|
||||
{
|
||||
op->ec_ = boost::system::error_code();
|
||||
reactor_.start_op(reactor::connect_op, impl.socket_,
|
||||
impl.reactor_data_, op, is_continuation, false);
|
||||
reactor_.start_op(reactor::connect_op, impl.socket_, impl.reactor_data_,
|
||||
op, is_continuation, false, on_immediate, immediate_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -297,5 +307,6 @@ void reactive_socket_service_base::start_connect_op(
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_IOCP)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/resolver_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -81,12 +81,10 @@ void resolver_service_base::base_notify_fork(
|
||||
work_thread_->join();
|
||||
work_thread_.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
work_scheduler_->restart();
|
||||
work_thread_.reset(new boost::asio::detail::thread(
|
||||
work_scheduler_runner(*work_scheduler_)));
|
||||
}
|
||||
}
|
||||
else if (fork_ev != execution_context::fork_prepare)
|
||||
{
|
||||
work_scheduler_->restart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/scheduler.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -20,11 +20,16 @@
|
||||
#include <boost/asio/detail/concurrency_hint.hpp>
|
||||
#include <boost/asio/detail/event.hpp>
|
||||
#include <boost/asio/detail/limits.hpp>
|
||||
#include <boost/asio/detail/reactor.hpp>
|
||||
#include <boost/asio/detail/scheduler.hpp>
|
||||
#include <boost/asio/detail/scheduler_thread_info.hpp>
|
||||
#include <boost/asio/detail/signal_blocker.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
# include <boost/asio/detail/io_uring_service.hpp>
|
||||
#else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
# include <boost/asio/detail/reactor.hpp>
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -105,7 +110,7 @@ struct scheduler::work_cleanup
|
||||
};
|
||||
|
||||
scheduler::scheduler(boost::asio::execution_context& ctx,
|
||||
int concurrency_hint, bool own_thread)
|
||||
int concurrency_hint, bool own_thread, get_task_func_type get_task)
|
||||
: boost::asio::detail::execution_context_service_base<scheduler>(ctx),
|
||||
one_thread_(concurrency_hint == 1
|
||||
|| !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
|
||||
@@ -115,6 +120,7 @@ scheduler::scheduler(boost::asio::execution_context& ctx,
|
||||
mutex_(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
|
||||
SCHEDULER, concurrency_hint)),
|
||||
task_(0),
|
||||
get_task_(get_task),
|
||||
task_interrupted_(true),
|
||||
outstanding_work_(0),
|
||||
stopped_(false),
|
||||
@@ -136,6 +142,10 @@ scheduler::~scheduler()
|
||||
{
|
||||
if (thread_)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
stop_all_threads(lock);
|
||||
lock.unlock();
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
}
|
||||
@@ -175,7 +185,7 @@ void scheduler::init_task()
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (!shutdown_ && !task_)
|
||||
{
|
||||
task_ = &use_service<reactor>(this->context());
|
||||
task_ = get_task_(this->context());
|
||||
op_queue_.push(&task_operation_);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
@@ -318,9 +328,21 @@ void scheduler::restart()
|
||||
void scheduler::compensating_work_started()
|
||||
{
|
||||
thread_info_base* this_thread = thread_call_stack::contains(this);
|
||||
BOOST_ASIO_ASSUME(this_thread != 0); // Only called from inside scheduler.
|
||||
++static_cast<thread_info*>(this_thread)->private_outstanding_work;
|
||||
}
|
||||
|
||||
bool scheduler::can_dispatch()
|
||||
{
|
||||
return thread_call_stack::contains(this) != 0;
|
||||
}
|
||||
|
||||
void scheduler::capture_current_exception()
|
||||
{
|
||||
if (thread_info_base* this_thread = thread_call_stack::contains(this))
|
||||
this_thread->capture_current_exception();
|
||||
}
|
||||
|
||||
void scheduler::post_immediate_completion(
|
||||
scheduler::operation* op, bool is_continuation)
|
||||
{
|
||||
@@ -344,6 +366,30 @@ void scheduler::post_immediate_completion(
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void scheduler::post_immediate_completions(std::size_t n,
|
||||
op_queue<scheduler::operation>& ops, bool is_continuation)
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_THREADS)
|
||||
if (one_thread_ || is_continuation)
|
||||
{
|
||||
if (thread_info_base* this_thread = thread_call_stack::contains(this))
|
||||
{
|
||||
static_cast<thread_info*>(this_thread)->private_outstanding_work
|
||||
+= static_cast<long>(n);
|
||||
static_cast<thread_info*>(this_thread)->private_op_queue.push(ops);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else // defined(BOOST_ASIO_HAS_THREADS)
|
||||
(void)is_continuation;
|
||||
#endif // defined(BOOST_ASIO_HAS_THREADS)
|
||||
|
||||
increment(outstanding_work_, static_cast<long>(n));
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(ops);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void scheduler::post_deferred_completion(scheduler::operation* op)
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_THREADS)
|
||||
@@ -445,6 +491,7 @@ std::size_t scheduler::do_run_one(mutex::scoped_lock& lock,
|
||||
|
||||
// Complete the operation. May throw an exception. Deletes the object.
|
||||
o->complete(this, ec, task_result);
|
||||
this_thread.rethrow_pending_exception();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -525,6 +572,7 @@ std::size_t scheduler::do_wait_one(mutex::scoped_lock& lock,
|
||||
|
||||
// Complete the operation. May throw an exception. Deletes the object.
|
||||
o->complete(this, ec, task_result);
|
||||
this_thread.rethrow_pending_exception();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -579,6 +627,7 @@ std::size_t scheduler::do_poll_one(mutex::scoped_lock& lock,
|
||||
|
||||
// Complete the operation. May throw an exception. Deletes the object.
|
||||
o->complete(this, ec, task_result);
|
||||
this_thread.rethrow_pending_exception();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -610,6 +659,15 @@ void scheduler::wake_one_thread_and_unlock(
|
||||
}
|
||||
}
|
||||
|
||||
scheduler_task* scheduler::get_default_task(boost::asio::execution_context& ctx)
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
return &use_service<io_uring_service>(ctx);
|
||||
#else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
return &use_service<reactor>(ctx);
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/select_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -23,12 +23,24 @@
|
||||
&& !defined(BOOST_ASIO_HAS_KQUEUE) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME))
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/win_iocp_io_context.hpp>
|
||||
#else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/scheduler.hpp>
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline void select_reactor::post_immediate_completion(
|
||||
operation* op, bool is_continuation) const
|
||||
{
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
@@ -74,6 +86,18 @@ std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& target,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/select_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -28,6 +28,12 @@
|
||||
#include <boost/asio/detail/signal_blocker.hpp>
|
||||
#include <boost/asio/detail/socket_ops.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/win_iocp_io_context.hpp>
|
||||
#else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/scheduler.hpp>
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -61,6 +67,7 @@ select_reactor::select_reactor(boost::asio::execution_context& ctx)
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
stop_thread_(false),
|
||||
thread_(0),
|
||||
restart_reactor_(this),
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
shutdown_(false)
|
||||
{
|
||||
@@ -81,13 +88,14 @@ void select_reactor::shutdown()
|
||||
shutdown_ = true;
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
stop_thread_ = true;
|
||||
if (thread_)
|
||||
interrupter_.interrupt();
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
lock.unlock();
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
if (thread_)
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
thread_ = 0;
|
||||
@@ -107,8 +115,12 @@ void select_reactor::shutdown()
|
||||
void select_reactor::notify_fork(
|
||||
boost::asio::execution_context::fork_event fork_ev)
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
(void)fork_ev;
|
||||
#else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
if (fork_ev == boost::asio::execution_context::fork_child)
|
||||
interrupter_.recreate();
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
}
|
||||
|
||||
void select_reactor::init_task()
|
||||
@@ -140,15 +152,23 @@ void select_reactor::move_descriptor(socket_type,
|
||||
{
|
||||
}
|
||||
|
||||
void select_reactor::call_post_immediate_completion(
|
||||
operation* op, bool is_continuation, const void* self)
|
||||
{
|
||||
static_cast<const select_reactor*>(self)->post_immediate_completion(
|
||||
op, is_continuation);
|
||||
}
|
||||
|
||||
void select_reactor::start_op(int op_type, socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&, reactor_op* op,
|
||||
bool is_continuation, bool)
|
||||
select_reactor::per_descriptor_data&, reactor_op* op, bool is_continuation,
|
||||
bool, void (*on_immediate)(operation*, bool, const void*),
|
||||
const void* immediate_arg)
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
post_immediate_completion(op, is_continuation);
|
||||
on_immediate(op, is_continuation, immediate_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,6 +185,19 @@ void select_reactor::cancel_ops(socket_type descriptor,
|
||||
cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void select_reactor::cancel_ops_by_key(socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&,
|
||||
int op_type, void* cancellation_key)
|
||||
{
|
||||
boost::asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(
|
||||
descriptor, ops, cancellation_key, boost::asio::error::operation_aborted);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
if (need_interrupt)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
void select_reactor::deregister_descriptor(socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&, bool)
|
||||
{
|
||||
@@ -240,7 +273,16 @@ void select_reactor::run(long usec, op_queue<operation>& ops)
|
||||
// Reset the interrupter.
|
||||
if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor()))
|
||||
{
|
||||
interrupter_.reset();
|
||||
if (!interrupter_.reset())
|
||||
{
|
||||
lock.lock();
|
||||
#if defined(BOOST_ASIO_HAS_IOCP)
|
||||
stop_thread_ = true;
|
||||
scheduler_.post_immediate_completion(&restart_reactor_, false);
|
||||
#else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
interrupter_.recreate();
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
}
|
||||
--retval;
|
||||
}
|
||||
|
||||
@@ -276,11 +318,36 @@ void select_reactor::run_thread()
|
||||
{
|
||||
lock.unlock();
|
||||
op_queue<operation> ops;
|
||||
run(true, ops);
|
||||
run(-1, ops);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
void select_reactor::restart_reactor::do_complete(void* owner, operation* base,
|
||||
const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
if (owner)
|
||||
{
|
||||
select_reactor* reactor = static_cast<restart_reactor*>(base)->reactor_;
|
||||
|
||||
if (reactor->thread_)
|
||||
{
|
||||
reactor->thread_->join();
|
||||
delete reactor->thread_;
|
||||
reactor->thread_ = 0;
|
||||
}
|
||||
|
||||
boost::asio::detail::mutex::scoped_lock lock(reactor->mutex_);
|
||||
reactor->interrupter_.recreate();
|
||||
reactor->stop_thread_ = false;
|
||||
lock.unlock();
|
||||
|
||||
boost::asio::detail::signal_blocker sb;
|
||||
reactor->thread_ =
|
||||
new boost::asio::detail::thread(thread_function(reactor));
|
||||
}
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
void select_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/service_registry.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/service_registry.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/signal_set_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -19,12 +19,17 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <boost/asio/detail/reactor.hpp>
|
||||
#include <boost/asio/detail/signal_blocker.hpp>
|
||||
#include <boost/asio/detail/signal_set_service.hpp>
|
||||
#include <boost/asio/detail/static_mutex.hpp>
|
||||
#include <boost/asio/detail/throw_exception.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
# include <boost/asio/detail/io_uring_service.hpp>
|
||||
#else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
# include <boost/asio/detail/reactor.hpp>
|
||||
#endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -50,12 +55,16 @@ struct signal_state
|
||||
|
||||
// A count of the number of objects that are registered for each signal.
|
||||
std::size_t registration_count_[max_signal_number];
|
||||
|
||||
// The flags used for each registered signal.
|
||||
signal_set_base::flags_t flags_[max_signal_number];
|
||||
};
|
||||
|
||||
signal_state* get_signal_state()
|
||||
{
|
||||
static signal_state state = {
|
||||
BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };
|
||||
BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0,
|
||||
{ 0 }, { signal_set_base::flags_t() } };
|
||||
return &state;
|
||||
}
|
||||
|
||||
@@ -86,11 +95,45 @@ void boost_asio_signal_handler(int signal_number)
|
||||
#if !defined(BOOST_ASIO_WINDOWS) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(__CYGWIN__)
|
||||
class signal_set_service::pipe_read_op : public reactor_op
|
||||
class signal_set_service::pipe_read_op :
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
public io_uring_operation
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
public reactor_op
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
{
|
||||
public:
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
pipe_read_op()
|
||||
: reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
|
||||
: io_uring_operation(boost::system::error_code(), &pipe_read_op::do_prepare,
|
||||
&pipe_read_op::do_perform, pipe_read_op::do_complete)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_prepare(io_uring_operation*, ::io_uring_sqe* sqe)
|
||||
{
|
||||
signal_state* state = get_signal_state();
|
||||
|
||||
int fd = state->read_descriptor_;
|
||||
::io_uring_prep_poll_add(sqe, fd, POLLIN);
|
||||
}
|
||||
|
||||
static bool do_perform(io_uring_operation*, bool)
|
||||
{
|
||||
signal_state* state = get_signal_state();
|
||||
|
||||
int fd = state->read_descriptor_;
|
||||
int signal_number = 0;
|
||||
while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
|
||||
if (signal_number >= 0 && signal_number < max_signal_number)
|
||||
signal_set_service::deliver_signal(signal_number);
|
||||
|
||||
return false;
|
||||
}
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
pipe_read_op()
|
||||
: reactor_op(boost::system::error_code(),
|
||||
&pipe_read_op::do_perform, pipe_read_op::do_complete)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -106,6 +149,7 @@ public:
|
||||
|
||||
return not_done;
|
||||
}
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
|
||||
static void do_complete(void* /*owner*/, operation* base,
|
||||
const boost::system::error_code& /*ec*/,
|
||||
@@ -125,7 +169,11 @@ signal_set_service::signal_set_service(execution_context& context)
|
||||
#if !defined(BOOST_ASIO_WINDOWS) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(__CYGWIN__)
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
io_uring_service_(boost::asio::use_service<io_uring_service>(context)),
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_(boost::asio::use_service<reactor>(context)),
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
@@ -137,7 +185,11 @@ signal_set_service::signal_set_service(execution_context& context)
|
||||
#if !defined(BOOST_ASIO_WINDOWS) \
|
||||
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(__CYGWIN__)
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
io_uring_service_.init_task();
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_.init_task();
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
@@ -187,8 +239,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev)
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
state->fork_prepared_ = true;
|
||||
lock.unlock();
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
(void)read_descriptor;
|
||||
io_uring_service_.deregister_io_object(io_object_data_);
|
||||
io_uring_service_.cleanup_io_object(io_object_data_);
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);
|
||||
reactor_.cleanup_descriptor_data(reactor_data_);
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
break;
|
||||
case execution_context::fork_parent:
|
||||
@@ -197,8 +255,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev)
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
state->fork_prepared_ = false;
|
||||
lock.unlock();
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
(void)read_descriptor;
|
||||
io_uring_service_.register_internal_io_object(io_object_data_,
|
||||
io_uring_service::read_op, new pipe_read_op);
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_.register_internal_descriptor(reactor::read_op,
|
||||
read_descriptor, reactor_data_, new pipe_read_op);
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
break;
|
||||
case execution_context::fork_child:
|
||||
@@ -210,8 +274,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev)
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
state->fork_prepared_ = false;
|
||||
lock.unlock();
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
(void)read_descriptor;
|
||||
io_uring_service_.register_internal_io_object(io_object_data_,
|
||||
io_uring_service::read_op, new pipe_read_op);
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
reactor_.register_internal_descriptor(reactor::read_op,
|
||||
read_descriptor, reactor_data_, new pipe_read_op);
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -241,8 +311,8 @@ void signal_set_service::destroy(
|
||||
}
|
||||
|
||||
boost::system::error_code signal_set_service::add(
|
||||
signal_set_service::implementation_type& impl,
|
||||
int signal_number, boost::system::error_code& ec)
|
||||
signal_set_service::implementation_type& impl, int signal_number,
|
||||
signal_set_base::flags_t f, boost::system::error_code& ec)
|
||||
{
|
||||
// Check that the signal number is valid.
|
||||
if (signal_number < 0 || signal_number >= max_signal_number)
|
||||
@@ -251,6 +321,15 @@ boost::system::error_code signal_set_service::add(
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Check that the specified flags are supported.
|
||||
#if !defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
if (f != signal_set_base::flags::dont_care)
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
return ec;
|
||||
}
|
||||
#endif // !defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
|
||||
signal_state* state = get_signal_state();
|
||||
static_mutex::scoped_lock lock(state->mutex_);
|
||||
|
||||
@@ -278,6 +357,8 @@ boost::system::error_code signal_set_service::add(
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = boost_asio_signal_handler;
|
||||
sigfillset(&sa.sa_mask);
|
||||
if (f != signal_set_base::flags::dont_care)
|
||||
sa.sa_flags = static_cast<int>(f);
|
||||
if (::sigaction(signal_number, &sa, 0) == -1)
|
||||
# else // defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR)
|
||||
@@ -292,7 +373,39 @@ boost::system::error_code signal_set_service::add(
|
||||
delete new_registration;
|
||||
return ec;
|
||||
}
|
||||
# if defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
state->flags_[signal_number] = f;
|
||||
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
}
|
||||
# if defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
// Otherwise check to see if the flags have changed.
|
||||
else if (f != signal_set_base::flags::dont_care)
|
||||
{
|
||||
if (f != state->flags_[signal_number])
|
||||
{
|
||||
using namespace std; // For memset.
|
||||
if (state->flags_[signal_number] != signal_set_base::flags::dont_care)
|
||||
{
|
||||
ec = boost::asio::error::invalid_argument;
|
||||
delete new_registration;
|
||||
return ec;
|
||||
}
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = boost_asio_signal_handler;
|
||||
sigfillset(&sa.sa_mask);
|
||||
sa.sa_flags = static_cast<int>(f);
|
||||
if (::sigaction(signal_number, &sa, 0) == -1)
|
||||
{
|
||||
ec = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
delete new_registration;
|
||||
return ec;
|
||||
}
|
||||
state->flags_[signal_number] = f;
|
||||
}
|
||||
}
|
||||
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
|
||||
// Record the new registration in the set.
|
||||
@@ -361,6 +474,9 @@ boost::system::error_code signal_set_service::remove(
|
||||
# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
|
||||
return ec;
|
||||
}
|
||||
# if defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
state->flags_[signal_number] = signal_set_base::flags_t();
|
||||
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
|
||||
@@ -415,6 +531,9 @@ boost::system::error_code signal_set_service::clear(
|
||||
# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
|
||||
return ec;
|
||||
}
|
||||
# if defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
state->flags_[reg->signal_number_] = signal_set_base::flags_t();
|
||||
# endif // defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
|
||||
|
||||
@@ -462,6 +581,33 @@ boost::system::error_code signal_set_service::cancel(
|
||||
return ec;
|
||||
}
|
||||
|
||||
void signal_set_service::cancel_ops_by_key(
|
||||
signal_set_service::implementation_type& impl, void* cancellation_key)
|
||||
{
|
||||
op_queue<operation> ops;
|
||||
{
|
||||
op_queue<signal_op> other_ops;
|
||||
signal_state* state = get_signal_state();
|
||||
static_mutex::scoped_lock lock(state->mutex_);
|
||||
|
||||
while (signal_op* op = impl.queue_.front())
|
||||
{
|
||||
impl.queue_.pop();
|
||||
if (op->cancellation_key_ == cancellation_key)
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
ops.push(op);
|
||||
}
|
||||
else
|
||||
other_ops.push(op);
|
||||
}
|
||||
|
||||
impl.queue_.push(other_ops);
|
||||
}
|
||||
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void signal_set_service::deliver_signal(int signal_number)
|
||||
{
|
||||
signal_state* state = get_signal_state();
|
||||
@@ -538,8 +684,14 @@ void signal_set_service::add_service(signal_set_service* service)
|
||||
// Register for pipe readiness notifications.
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
lock.unlock();
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
(void)read_descriptor;
|
||||
service->io_uring_service_.register_internal_io_object(
|
||||
service->io_object_data_, io_uring_service::read_op, new pipe_read_op);
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
service->reactor_.register_internal_descriptor(reactor::read_op,
|
||||
read_descriptor, service->reactor_data_, new pipe_read_op);
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
@@ -558,10 +710,17 @@ void signal_set_service::remove_service(signal_set_service* service)
|
||||
// Disable the pipe readiness notifications.
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
lock.unlock();
|
||||
# if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
(void)read_descriptor;
|
||||
service->io_uring_service_.deregister_io_object(service->io_object_data_);
|
||||
service->io_uring_service_.cleanup_io_object(service->io_object_data_);
|
||||
lock.lock();
|
||||
# else // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
service->reactor_.deregister_internal_descriptor(
|
||||
read_descriptor, service->reactor_data_);
|
||||
service->reactor_.cleanup_descriptor_data(service->reactor_data_);
|
||||
lock.lock();
|
||||
# endif // defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
#endif // !defined(BOOST_ASIO_WINDOWS)
|
||||
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
// detail/impl/socket_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -61,11 +61,11 @@ void socket_select_interrupter::open_descriptors()
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);
|
||||
addr.sin_port = 0;
|
||||
if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
|
||||
if (socket_ops::bind(acceptor.get(), &addr,
|
||||
addr_len, ec) == socket_error_retval)
|
||||
boost::asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
|
||||
if (socket_ops::getsockname(acceptor.get(), &addr,
|
||||
&addr_len, ec) == socket_error_retval)
|
||||
boost::asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
@@ -84,7 +84,7 @@ void socket_select_interrupter::open_descriptors()
|
||||
if (client.get() == invalid_socket)
|
||||
boost::asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
|
||||
if (socket_ops::connect(client.get(), &addr,
|
||||
addr_len, ec) == socket_error_retval)
|
||||
boost::asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
@@ -156,11 +156,20 @@ bool socket_select_interrupter::reset()
|
||||
socket_ops::buf b;
|
||||
socket_ops::init_buf(b, data, sizeof(data));
|
||||
boost::system::error_code ec;
|
||||
int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
|
||||
return was_interrupted;
|
||||
for (;;)
|
||||
{
|
||||
int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
|
||||
if (bytes_read == sizeof(data))
|
||||
continue;
|
||||
if (bytes_read > 0)
|
||||
return true;
|
||||
if (bytes_read == 0)
|
||||
return false;
|
||||
if (ec == boost::asio::error::would_block
|
||||
|| ec == boost::asio::error::try_again)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/strand_executor_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,11 +15,13 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/call_stack.hpp>
|
||||
#include <boost/asio/detail/fenced_block.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/recycling_allocator.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/defer.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -27,8 +29,132 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename F, typename Allocator>
|
||||
class strand_executor_service::allocator_binder
|
||||
{
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
allocator_binder(BOOST_ASIO_MOVE_ARG(F) f, const Allocator& a)
|
||||
: f_(BOOST_ASIO_MOVE_CAST(F)(f)),
|
||||
allocator_(a)
|
||||
{
|
||||
}
|
||||
|
||||
allocator_binder(const allocator_binder& other)
|
||||
: f_(other.f_),
|
||||
allocator_(other.allocator_)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
allocator_binder(allocator_binder&& other)
|
||||
: f_(BOOST_ASIO_MOVE_CAST(F)(other.f_)),
|
||||
allocator_(BOOST_ASIO_MOVE_CAST(allocator_type)(other.allocator_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return allocator_;
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
allocator_type allocator_;
|
||||
};
|
||||
|
||||
template <typename Executor>
|
||||
class strand_executor_service::invoker
|
||||
class strand_executor_service::invoker<Executor,
|
||||
typename enable_if<
|
||||
execution::is_executor<Executor>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
invoker(const implementation_type& impl, Executor& ex)
|
||||
: impl_(impl),
|
||||
executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
|
||||
{
|
||||
}
|
||||
|
||||
invoker(const invoker& other)
|
||||
: impl_(other.impl_),
|
||||
executor_(other.executor_)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE)
|
||||
invoker(invoker&& other)
|
||||
: impl_(BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_)),
|
||||
executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
|
||||
{
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE)
|
||||
|
||||
struct on_invoker_exit
|
||||
{
|
||||
invoker* this_;
|
||||
|
||||
~on_invoker_exit()
|
||||
{
|
||||
if (push_waiting_to_ready(this_->impl_))
|
||||
{
|
||||
recycling_allocator<void> allocator;
|
||||
executor_type ex = this_->executor_;
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
boost::asio::prefer(
|
||||
boost::asio::require(
|
||||
BOOST_ASIO_MOVE_CAST(executor_type)(ex),
|
||||
execution::blocking.never),
|
||||
execution::allocator(allocator)
|
||||
).execute(BOOST_ASIO_MOVE_CAST(invoker)(*this_));
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
execution::execute(
|
||||
boost::asio::prefer(
|
||||
boost::asio::require(
|
||||
BOOST_ASIO_MOVE_CAST(executor_type)(ex),
|
||||
execution::blocking.never),
|
||||
execution::allocator(allocator)),
|
||||
BOOST_ASIO_MOVE_CAST(invoker)(*this_));
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void operator()()
|
||||
{
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_invoker_exit on_exit = { this };
|
||||
(void)on_exit;
|
||||
|
||||
run_ready_handlers(impl_);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename decay<
|
||||
typename prefer_result<
|
||||
Executor,
|
||||
execution::outstanding_work_t::tracked_t
|
||||
>::type
|
||||
>::type executor_type;
|
||||
|
||||
implementation_type impl_;
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
|
||||
|
||||
template <typename Executor>
|
||||
class strand_executor_service::invoker<Executor,
|
||||
typename enable_if<
|
||||
!execution::is_executor<Executor>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
invoker(const implementation_type& impl, Executor& ex)
|
||||
@@ -57,13 +183,7 @@ public:
|
||||
|
||||
~on_invoker_exit()
|
||||
{
|
||||
this_->impl_->mutex_->lock();
|
||||
this_->impl_->ready_queue_.push(this_->impl_->waiting_queue_);
|
||||
bool more_handlers = this_->impl_->locked_ =
|
||||
!this_->impl_->ready_queue_.empty();
|
||||
this_->impl_->mutex_->unlock();
|
||||
|
||||
if (more_handlers)
|
||||
if (push_waiting_to_ready(this_->impl_))
|
||||
{
|
||||
Executor ex(this_->work_.get_executor());
|
||||
recycling_allocator<void> allocator;
|
||||
@@ -74,21 +194,11 @@ public:
|
||||
|
||||
void operator()()
|
||||
{
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl_.get());
|
||||
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_invoker_exit on_exit = { this };
|
||||
(void)on_exit;
|
||||
|
||||
// Run all ready handlers. No lock is required since the ready queue is
|
||||
// accessed only within the strand.
|
||||
boost::system::error_code ec;
|
||||
while (scheduler_operation* o = impl_->ready_queue_.front())
|
||||
{
|
||||
impl_->ready_queue_.pop();
|
||||
o->complete(impl_.get(), ec, 0);
|
||||
}
|
||||
run_ready_handlers(impl_);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -96,6 +206,72 @@ private:
|
||||
executor_work_guard<Executor> work_;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
|
||||
|
||||
template <typename Executor, typename Function>
|
||||
inline void strand_executor_service::execute(const implementation_type& impl,
|
||||
Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
typename enable_if<
|
||||
can_query<Executor, execution::allocator_t<void> >::value
|
||||
>::type*)
|
||||
{
|
||||
return strand_executor_service::do_execute(impl, ex,
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function),
|
||||
boost::asio::query(ex, execution::allocator));
|
||||
}
|
||||
|
||||
template <typename Executor, typename Function>
|
||||
inline void strand_executor_service::execute(const implementation_type& impl,
|
||||
Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function,
|
||||
typename enable_if<
|
||||
!can_query<Executor, execution::allocator_t<void> >::value
|
||||
>::type*)
|
||||
{
|
||||
return strand_executor_service::do_execute(impl, ex,
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function),
|
||||
std::allocator<void>());
|
||||
}
|
||||
|
||||
template <typename Executor, typename Function, typename Allocator>
|
||||
void strand_executor_service::do_execute(const implementation_type& impl,
|
||||
Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a)
|
||||
{
|
||||
typedef typename decay<Function>::type function_type;
|
||||
|
||||
// If the executor is not never-blocking, and we are already in the strand,
|
||||
// then the function can run immediately.
|
||||
if (boost::asio::query(ex, execution::blocking) != execution::blocking.never
|
||||
&& running_in_this_thread(impl))
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
|
||||
fenced_block b(fenced_block::full);
|
||||
boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(function), a);
|
||||
|
||||
BOOST_ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
|
||||
"strand_executor", impl.get(), 0, "execute"));
|
||||
|
||||
// Add the function to the strand and schedule the strand if required.
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
{
|
||||
#if defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
ex.execute(invoker<Executor>(impl, ex));
|
||||
#else // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
execution::execute(ex, invoker<Executor>(impl, ex));
|
||||
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Executor, typename Function, typename Allocator>
|
||||
void strand_executor_service::dispatch(const implementation_type& impl,
|
||||
Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a)
|
||||
@@ -103,7 +279,7 @@ void strand_executor_service::dispatch(const implementation_type& impl,
|
||||
typedef typename decay<Function>::type function_type;
|
||||
|
||||
// If we are already in the strand then the function can run immediately.
|
||||
if (call_stack<strand_impl>::contains(impl.get()))
|
||||
if (running_in_this_thread(impl))
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
@@ -125,7 +301,11 @@ void strand_executor_service::dispatch(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.dispatch(invoker<Executor>(impl, ex), a);
|
||||
{
|
||||
boost::asio::dispatch(ex,
|
||||
allocator_binder<invoker<Executor>, Allocator>(
|
||||
invoker<Executor>(impl, ex), a));
|
||||
}
|
||||
}
|
||||
|
||||
// Request invocation of the given function and return immediately.
|
||||
@@ -147,7 +327,11 @@ void strand_executor_service::post(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.post(invoker<Executor>(impl, ex), a);
|
||||
{
|
||||
boost::asio::post(ex,
|
||||
allocator_binder<invoker<Executor>, Allocator>(
|
||||
invoker<Executor>(impl, ex), a));
|
||||
}
|
||||
}
|
||||
|
||||
// Request invocation of the given function and return immediately.
|
||||
@@ -169,7 +353,11 @@ void strand_executor_service::defer(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.defer(invoker<Executor>(impl, ex), a);
|
||||
{
|
||||
boost::asio::defer(ex,
|
||||
allocator_binder<invoker<Executor>, Allocator>(
|
||||
invoker<Executor>(impl, ex), a));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/strand_executor_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -127,6 +127,30 @@ bool strand_executor_service::running_in_this_thread(
|
||||
return !!call_stack<strand_impl>::contains(impl.get());
|
||||
}
|
||||
|
||||
bool strand_executor_service::push_waiting_to_ready(implementation_type& impl)
|
||||
{
|
||||
impl->mutex_->lock();
|
||||
impl->ready_queue_.push(impl->waiting_queue_);
|
||||
bool more_handlers = impl->locked_ = !impl->ready_queue_.empty();
|
||||
impl->mutex_->unlock();
|
||||
return more_handlers;
|
||||
}
|
||||
|
||||
void strand_executor_service::run_ready_handlers(implementation_type& impl)
|
||||
{
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl.get());
|
||||
|
||||
// Run all ready handlers. No lock is required since the ready queue is
|
||||
// accessed only within the strand.
|
||||
boost::system::error_code ec;
|
||||
while (scheduler_operation* o = impl->ready_queue_.front())
|
||||
{
|
||||
impl->ready_queue_.pop();
|
||||
o->complete(impl.get(), ec, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/strand_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,7 +15,6 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/call_stack.hpp>
|
||||
#include <boost/asio/detail/completion_handler.hpp>
|
||||
#include <boost/asio/detail/fenced_block.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
@@ -34,29 +33,12 @@ inline strand_service::strand_impl::strand_impl()
|
||||
{
|
||||
}
|
||||
|
||||
struct strand_service::on_dispatch_exit
|
||||
{
|
||||
io_context_impl* io_context_;
|
||||
strand_impl* impl_;
|
||||
|
||||
~on_dispatch_exit()
|
||||
{
|
||||
impl_->mutex_.lock();
|
||||
impl_->ready_queue_.push(impl_->waiting_queue_);
|
||||
bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();
|
||||
impl_->mutex_.unlock();
|
||||
|
||||
if (more_handlers)
|
||||
io_context_->post_immediate_completion(impl_, false);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
void strand_service::dispatch(strand_service::implementation_type& impl,
|
||||
Handler& handler)
|
||||
{
|
||||
// If we are already in the strand then the handler can run immediately.
|
||||
if (call_stack<strand_impl>::contains(impl))
|
||||
if (running_in_this_thread(impl))
|
||||
{
|
||||
fenced_block b(fenced_block::full);
|
||||
boost_asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
@@ -64,30 +46,17 @@ void strand_service::dispatch(strand_service::implementation_type& impl,
|
||||
}
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typedef completion_handler<Handler, io_context::executor_type> op;
|
||||
typename op::ptr p = { boost::asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_context_.get_executor());
|
||||
|
||||
BOOST_ASIO_HANDLER_CREATION((this->context(),
|
||||
*p.p, "strand", impl, 0, "dispatch"));
|
||||
|
||||
bool dispatch_immediately = do_dispatch(impl, p.p);
|
||||
operation* o = p.p;
|
||||
p.v = p.p = 0;
|
||||
|
||||
if (dispatch_immediately)
|
||||
{
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl);
|
||||
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_dispatch_exit on_exit = { &io_context_, impl };
|
||||
(void)on_exit;
|
||||
|
||||
completion_handler<Handler>::do_complete(
|
||||
&io_context_, o, boost::system::error_code(), 0);
|
||||
}
|
||||
do_dispatch(impl, o);
|
||||
}
|
||||
|
||||
// Request the io_context to invoke the given handler and return immediately.
|
||||
@@ -99,10 +68,10 @@ void strand_service::post(strand_service::implementation_type& impl,
|
||||
boost_asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typedef completion_handler<Handler, io_context::executor_type> op;
|
||||
typename op::ptr p = { boost::asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_context_.get_executor());
|
||||
|
||||
BOOST_ASIO_HANDLER_CREATION((this->context(),
|
||||
*p.p, "strand", impl, 0, "post"));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/strand_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -44,7 +44,8 @@ struct strand_service::on_do_complete_exit
|
||||
|
||||
strand_service::strand_service(boost::asio::io_context& io_context)
|
||||
: boost::asio::detail::service_base<strand_service>(io_context),
|
||||
io_context_(boost::asio::use_service<io_context_impl>(io_context)),
|
||||
io_context_(io_context),
|
||||
io_context_impl_(boost::asio::use_service<io_context_impl>(io_context)),
|
||||
mutex_(),
|
||||
salt_(0)
|
||||
{
|
||||
@@ -91,18 +92,44 @@ bool strand_service::running_in_this_thread(
|
||||
return call_stack<strand_impl>::contains(impl) != 0;
|
||||
}
|
||||
|
||||
bool strand_service::do_dispatch(implementation_type& impl, operation* op)
|
||||
struct strand_service::on_dispatch_exit
|
||||
{
|
||||
io_context_impl* io_context_impl_;
|
||||
strand_impl* impl_;
|
||||
|
||||
~on_dispatch_exit()
|
||||
{
|
||||
impl_->mutex_.lock();
|
||||
impl_->ready_queue_.push(impl_->waiting_queue_);
|
||||
bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();
|
||||
impl_->mutex_.unlock();
|
||||
|
||||
if (more_handlers)
|
||||
io_context_impl_->post_immediate_completion(impl_, false);
|
||||
}
|
||||
};
|
||||
|
||||
void strand_service::do_dispatch(implementation_type& impl, operation* op)
|
||||
{
|
||||
// If we are running inside the io_context, and no other handler already
|
||||
// holds the strand lock, then the handler can run immediately.
|
||||
bool can_dispatch = io_context_.can_dispatch();
|
||||
bool can_dispatch = io_context_impl_.can_dispatch();
|
||||
impl->mutex_.lock();
|
||||
if (can_dispatch && !impl->locked_)
|
||||
{
|
||||
// Immediate invocation is allowed.
|
||||
impl->locked_ = true;
|
||||
impl->mutex_.unlock();
|
||||
return true;
|
||||
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl);
|
||||
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_dispatch_exit on_exit = { &io_context_impl_, impl };
|
||||
(void)on_exit;
|
||||
|
||||
op->complete(&io_context_impl_, boost::system::error_code(), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (impl->locked_)
|
||||
@@ -118,10 +145,8 @@ bool strand_service::do_dispatch(implementation_type& impl, operation* op)
|
||||
impl->locked_ = true;
|
||||
impl->mutex_.unlock();
|
||||
impl->ready_queue_.push(op);
|
||||
io_context_.post_immediate_completion(impl, false);
|
||||
io_context_impl_.post_immediate_completion(impl, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void strand_service::do_post(implementation_type& impl,
|
||||
@@ -141,7 +166,7 @@ void strand_service::do_post(implementation_type& impl,
|
||||
impl->locked_ = true;
|
||||
impl->mutex_.unlock();
|
||||
impl->ready_queue_.push(op);
|
||||
io_context_.post_immediate_completion(impl, is_continuation);
|
||||
io_context_impl_.post_immediate_completion(impl, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
linx64/include/boost/asio/detail/impl/thread_context.ipp
Normal file
37
linx64/include/boost/asio/detail/impl/thread_context.ipp
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// detail/impl/thread_context.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
thread_info_base* thread_context::top_of_thread_call_stack()
|
||||
{
|
||||
return thread_call_stack::top();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/throw_error.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/detail/throw_exception.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
@@ -26,16 +25,21 @@ namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
void do_throw_error(const boost::system::error_code& err)
|
||||
void do_throw_error(
|
||||
const boost::system::error_code& err
|
||||
BOOST_ASIO_SOURCE_LOCATION_PARAM)
|
||||
{
|
||||
boost::system::system_error e(err);
|
||||
boost::asio::detail::throw_exception(e);
|
||||
boost::asio::detail::throw_exception(e BOOST_ASIO_SOURCE_LOCATION_ARG);
|
||||
}
|
||||
|
||||
void do_throw_error(const boost::system::error_code& err, const char* location)
|
||||
void do_throw_error(
|
||||
const boost::system::error_code& err,
|
||||
const char* location
|
||||
BOOST_ASIO_SOURCE_LOCATION_PARAM)
|
||||
{
|
||||
boost::system::system_error e(err, location);
|
||||
boost::asio::detail::throw_exception(e);
|
||||
boost::asio::detail::throw_exception(e BOOST_ASIO_SOURCE_LOCATION_ARG);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/timer_queue_ptime.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -76,6 +76,12 @@ std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
|
||||
return impl_.cancel_timer(timer, ops, max_cancelled);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer_by_key(
|
||||
per_timer_data* timer, op_queue<operation>& ops, void* cancellation_key)
|
||||
{
|
||||
impl_.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer(
|
||||
per_timer_data& target, per_timer_data& source)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/timer_queue_set.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/win_event.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
267
linx64/include/boost/asio/detail/impl/win_iocp_file_service.ipp
Normal file
267
linx64/include/boost/asio/detail/impl/win_iocp_file_service.ipp
Normal file
@@ -0,0 +1,267 @@
|
||||
//
|
||||
// detail/impl/win_iocp_file_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_FILE) \
|
||||
&& defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
|
||||
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/asio/detail/win_iocp_file_service.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_iocp_file_service::win_iocp_file_service(
|
||||
execution_context& context)
|
||||
: execution_context_service_base<win_iocp_file_service>(context),
|
||||
handle_service_(context),
|
||||
nt_flush_buffers_file_ex_(0)
|
||||
{
|
||||
if (FARPROC nt_flush_buffers_file_ex_ptr = ::GetProcAddress(
|
||||
::GetModuleHandleA("NTDLL"), "NtFlushBuffersFileEx"))
|
||||
{
|
||||
nt_flush_buffers_file_ex_ = reinterpret_cast<nt_flush_buffers_file_ex_fn>(
|
||||
reinterpret_cast<void*>(nt_flush_buffers_file_ex_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_file_service::shutdown()
|
||||
{
|
||||
handle_service_.shutdown();
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_file_service::open(
|
||||
win_iocp_file_service::implementation_type& impl,
|
||||
const char* path, file_base::flags open_flags,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
DWORD access = 0;
|
||||
if ((open_flags & file_base::read_only) != 0)
|
||||
access = GENERIC_READ;
|
||||
else if ((open_flags & file_base::write_only) != 0)
|
||||
access = GENERIC_WRITE;
|
||||
else if ((open_flags & file_base::read_write) != 0)
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
|
||||
DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
DWORD disposition = 0;
|
||||
if ((open_flags & file_base::create) != 0)
|
||||
{
|
||||
if ((open_flags & file_base::exclusive) != 0)
|
||||
disposition = CREATE_NEW;
|
||||
else
|
||||
disposition = OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((open_flags & file_base::truncate) != 0)
|
||||
disposition = TRUNCATE_EXISTING;
|
||||
else
|
||||
disposition = OPEN_EXISTING;
|
||||
}
|
||||
|
||||
DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
|
||||
if (impl.is_stream_)
|
||||
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
else
|
||||
flags |= FILE_FLAG_RANDOM_ACCESS;
|
||||
if ((open_flags & file_base::sync_all_on_write) != 0)
|
||||
flags |= FILE_FLAG_WRITE_THROUGH;
|
||||
|
||||
HANDLE handle = ::CreateFileA(path, access, share, 0, disposition, flags, 0);
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (disposition == OPEN_ALWAYS && (open_flags & file_base::truncate) != 0)
|
||||
{
|
||||
if (!::SetEndOfFile(handle))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
handle_service_.assign(impl, handle, ec);
|
||||
if (ec)
|
||||
::CloseHandle(handle);
|
||||
impl.offset_ = 0;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t win_iocp_file_service::size(
|
||||
const win_iocp_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec) const
|
||||
{
|
||||
LARGE_INTEGER result;
|
||||
if (::GetFileSizeEx(native_handle(impl), &result))
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return static_cast<uint64_t>(result.QuadPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_file_service::resize(
|
||||
win_iocp_file_service::implementation_type& impl,
|
||||
uint64_t n, boost::system::error_code& ec)
|
||||
{
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = n;
|
||||
if (::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))
|
||||
{
|
||||
BOOL result = ::SetEndOfFile(native_handle(impl));
|
||||
DWORD last_error = ::GetLastError();
|
||||
|
||||
distance.QuadPart = static_cast<LONGLONG>(impl.offset_);
|
||||
if (!::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))
|
||||
{
|
||||
result = FALSE;
|
||||
last_error = ::GetLastError();
|
||||
}
|
||||
|
||||
if (result)
|
||||
boost::asio::error::clear(ec);
|
||||
else
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_file_service::sync_all(
|
||||
win_iocp_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
BOOL result = ::FlushFileBuffers(native_handle(impl));
|
||||
if (result)
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return ec;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_file_service::sync_data(
|
||||
win_iocp_file_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (nt_flush_buffers_file_ex_)
|
||||
{
|
||||
io_status_block status = {};
|
||||
if (!nt_flush_buffers_file_ex_(native_handle(impl),
|
||||
flush_flags_file_data_sync_only, 0, 0, &status))
|
||||
{
|
||||
boost::asio::error::clear(ec);
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
return sync_all(impl, ec);
|
||||
}
|
||||
|
||||
uint64_t win_iocp_file_service::seek(
|
||||
win_iocp_file_service::implementation_type& impl, int64_t offset,
|
||||
file_base::seek_basis whence, boost::system::error_code& ec)
|
||||
{
|
||||
DWORD method;
|
||||
switch (whence)
|
||||
{
|
||||
case file_base::seek_set:
|
||||
method = FILE_BEGIN;
|
||||
break;
|
||||
case file_base::seek_cur:
|
||||
method = FILE_BEGIN;
|
||||
offset = static_cast<int64_t>(impl.offset_) + offset;
|
||||
break;
|
||||
case file_base::seek_end:
|
||||
method = FILE_END;
|
||||
break;
|
||||
default:
|
||||
ec = boost::asio::error::invalid_argument;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LARGE_INTEGER distance, new_offset;
|
||||
distance.QuadPart = offset;
|
||||
if (::SetFilePointerEx(native_handle(impl), distance, &new_offset, method))
|
||||
{
|
||||
impl.offset_ = new_offset.QuadPart;
|
||||
boost::asio::error::clear(ec);
|
||||
return impl.offset_;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec.assign(last_error, boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_FILE)
|
||||
// && defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/win_iocp_handle_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
win_iocp_handle_service::win_iocp_handle_service(execution_context& context)
|
||||
: execution_context_service_base<win_iocp_handle_service>(context),
|
||||
iocp_service_(boost::asio::use_service<win_iocp_io_context>(context)),
|
||||
nt_set_info_(0),
|
||||
mutex_(),
|
||||
impl_list_(0)
|
||||
{
|
||||
@@ -183,11 +184,15 @@ boost::system::error_code win_iocp_handle_service::assign(
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (iocp_service_.register_handle(handle, ec))
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
impl.handle_ = handle;
|
||||
ec = boost::system::error_code();
|
||||
@@ -222,9 +227,47 @@ boost::system::error_code win_iocp_handle_service::close(
|
||||
ec = boost::system::error_code();
|
||||
}
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
win_iocp_handle_service::native_handle_type win_iocp_handle_service::release(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
cancel(impl, ec);
|
||||
if (ec)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
nt_set_info_fn fn = get_nt_set_info();
|
||||
if (fn == 0)
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
ULONG_PTR iosb[2] = { 0, 0 };
|
||||
void* info[2] = { 0, 0 };
|
||||
if (fn(impl.handle_, iosb, &info, sizeof(info),
|
||||
61 /* FileReplaceCompletionInformation */))
|
||||
{
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
native_handle_type tmp = impl.handle_;
|
||||
impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_handle_service::cancel(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
boost::system::error_code& ec)
|
||||
@@ -232,6 +275,7 @@ boost::system::error_code win_iocp_handle_service::cancel(
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -243,7 +287,8 @@ boost::system::error_code win_iocp_handle_service::cancel(
|
||||
{
|
||||
// The version of Windows supports cancellation from any thread.
|
||||
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
|
||||
cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
|
||||
cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(
|
||||
reinterpret_cast<void*>(cancel_io_ex_ptr));
|
||||
if (!cancel_io_ex(impl.handle_, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
@@ -292,6 +337,7 @@ boost::system::error_code win_iocp_handle_service::cancel(
|
||||
ec = boost::asio::error::operation_not_supported;
|
||||
}
|
||||
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -302,6 +348,7 @@ size_t win_iocp_handle_service::do_write(
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -315,6 +362,7 @@ size_t win_iocp_handle_service::do_write(
|
||||
overlapped_wrapper overlapped(ec);
|
||||
if (ec)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -330,6 +378,7 @@ size_t win_iocp_handle_service::do_write(
|
||||
{
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -343,6 +392,7 @@ size_t win_iocp_handle_service::do_write(
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -394,6 +444,7 @@ size_t win_iocp_handle_service::do_read(
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::bad_descriptor;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -407,6 +458,7 @@ size_t win_iocp_handle_service::do_read(
|
||||
overlapped_wrapper overlapped(ec);
|
||||
if (ec)
|
||||
{
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -429,6 +481,7 @@ size_t win_iocp_handle_service::do_read(
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
}
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -449,6 +502,7 @@ size_t win_iocp_handle_service::do_read(
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
}
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0;
|
||||
}
|
||||
|
||||
@@ -515,6 +569,47 @@ void win_iocp_handle_service::close_for_destruction(implementation_type& impl)
|
||||
}
|
||||
}
|
||||
|
||||
win_iocp_handle_service::nt_set_info_fn
|
||||
win_iocp_handle_service::get_nt_set_info()
|
||||
{
|
||||
void* ptr = interlocked_compare_exchange_pointer(&nt_set_info_, 0, 0);
|
||||
if (!ptr)
|
||||
{
|
||||
if (HMODULE h = ::GetModuleHandleA("NTDLL.DLL"))
|
||||
ptr = reinterpret_cast<void*>(GetProcAddress(h, "NtSetInformationFile"));
|
||||
|
||||
// On failure, set nt_set_info_ to a special value to indicate that the
|
||||
// NtSetInformationFile function is unavailable. That way we won't bother
|
||||
// trying to look it up again.
|
||||
interlocked_exchange_pointer(&nt_set_info_, ptr ? ptr : this);
|
||||
}
|
||||
|
||||
return reinterpret_cast<nt_set_info_fn>(ptr == this ? 0 : ptr);
|
||||
}
|
||||
|
||||
void* win_iocp_handle_service::interlocked_compare_exchange_pointer(
|
||||
void** dest, void* exch, void* cmp)
|
||||
{
|
||||
#if defined(_M_IX86)
|
||||
return reinterpret_cast<void*>(InterlockedCompareExchange(
|
||||
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
|
||||
reinterpret_cast<LONG>(cmp)));
|
||||
#else
|
||||
return InterlockedCompareExchangePointer(dest, exch, cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void* win_iocp_handle_service::interlocked_exchange_pointer(
|
||||
void** dest, void* val)
|
||||
{
|
||||
#if defined(_M_IX86)
|
||||
return reinterpret_cast<void*>(InterlockedExchange(
|
||||
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
|
||||
#else
|
||||
return InterlockedExchangePointer(dest, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/win_iocp_io_context.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -77,10 +77,27 @@ std::size_t win_iocp_io_context::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
op_queue<win_iocp_operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
|
||||
lock.unlock();
|
||||
post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_context::cancel_timer_by_key(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data* timer,
|
||||
void* cancellation_key)
|
||||
{
|
||||
// If the service has been shut down we silently ignore the cancellation.
|
||||
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
op_queue<win_iocp_operation> ops;
|
||||
queue.cancel_timer_by_key(timer, ops, cancellation_key);
|
||||
lock.unlock();
|
||||
post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_context::move_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& to,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/win_iocp_io_context.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -52,7 +52,7 @@ struct win_iocp_io_context::thread_function
|
||||
|
||||
struct win_iocp_io_context::work_finished_on_block_exit
|
||||
{
|
||||
~work_finished_on_block_exit()
|
||||
~work_finished_on_block_exit() BOOST_ASIO_NOEXCEPT_IF(false)
|
||||
{
|
||||
io_context_->work_finished();
|
||||
}
|
||||
@@ -114,6 +114,7 @@ win_iocp_io_context::~win_iocp_io_context()
|
||||
{
|
||||
if (thread_.get())
|
||||
{
|
||||
stop();
|
||||
thread_->join();
|
||||
thread_.reset();
|
||||
}
|
||||
@@ -132,6 +133,7 @@ void win_iocp_io_context::shutdown()
|
||||
|
||||
if (thread_.get())
|
||||
{
|
||||
stop();
|
||||
thread_->join();
|
||||
thread_.reset();
|
||||
::InterlockedDecrement(&outstanding_work_);
|
||||
@@ -167,7 +169,10 @@ void win_iocp_io_context::shutdown()
|
||||
}
|
||||
|
||||
if (timer_thread_.get())
|
||||
{
|
||||
timer_thread_->join();
|
||||
timer_thread_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_code win_iocp_io_context::register_handle(
|
||||
@@ -199,7 +204,7 @@ size_t win_iocp_io_context::run(boost::system::error_code& ec)
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(INFINITE, ec))
|
||||
while (do_one(INFINITE, this_thread, ec))
|
||||
if (n != (std::numeric_limits<size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
@@ -217,7 +222,7 @@ size_t win_iocp_io_context::run_one(boost::system::error_code& ec)
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
return do_one(INFINITE, ec);
|
||||
return do_one(INFINITE, this_thread, ec);
|
||||
}
|
||||
|
||||
size_t win_iocp_io_context::wait_one(long usec, boost::system::error_code& ec)
|
||||
@@ -232,7 +237,7 @@ size_t win_iocp_io_context::wait_one(long usec, boost::system::error_code& ec)
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), ec);
|
||||
return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), this_thread, ec);
|
||||
}
|
||||
|
||||
size_t win_iocp_io_context::poll(boost::system::error_code& ec)
|
||||
@@ -248,7 +253,7 @@ size_t win_iocp_io_context::poll(boost::system::error_code& ec)
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(0, ec))
|
||||
while (do_one(0, this_thread, ec))
|
||||
if (n != (std::numeric_limits<size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
@@ -266,7 +271,7 @@ size_t win_iocp_io_context::poll_one(boost::system::error_code& ec)
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
return do_one(0, ec);
|
||||
return do_one(0, this_thread, ec);
|
||||
}
|
||||
|
||||
void win_iocp_io_context::stop()
|
||||
@@ -286,6 +291,17 @@ void win_iocp_io_context::stop()
|
||||
}
|
||||
}
|
||||
|
||||
bool win_iocp_io_context::can_dispatch()
|
||||
{
|
||||
return thread_call_stack::contains(this) != 0;
|
||||
}
|
||||
|
||||
void win_iocp_io_context::capture_current_exception()
|
||||
{
|
||||
if (thread_info_base* this_thread = thread_call_stack::contains(this))
|
||||
this_thread->capture_current_exception();
|
||||
}
|
||||
|
||||
void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op)
|
||||
{
|
||||
// Flag the operation as ready.
|
||||
@@ -395,7 +411,8 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op,
|
||||
}
|
||||
}
|
||||
|
||||
size_t win_iocp_io_context::do_one(DWORD msec, boost::system::error_code& ec)
|
||||
size_t win_iocp_io_context::do_one(DWORD msec,
|
||||
win_iocp_thread_info& this_thread, boost::system::error_code& ec)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -457,6 +474,7 @@ size_t win_iocp_io_context::do_one(DWORD msec, boost::system::error_code& ec)
|
||||
(void)on_exit;
|
||||
|
||||
op->complete(this, result_ec, bytes_transferred);
|
||||
this_thread.rethrow_pending_exception();
|
||||
ec = boost::system::error_code();
|
||||
return 1;
|
||||
}
|
||||
@@ -513,6 +531,7 @@ size_t win_iocp_io_context::do_one(DWORD msec, boost::system::error_code& ec)
|
||||
|
||||
DWORD win_iocp_io_context::get_gqcs_timeout()
|
||||
{
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
|
||||
OSVERSIONINFOEX osvi;
|
||||
ZeroMemory(&osvi, sizeof(osvi));
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
@@ -525,6 +544,9 @@ DWORD win_iocp_io_context::get_gqcs_timeout()
|
||||
return INFINITE;
|
||||
|
||||
return default_gqcs_timeout;
|
||||
#else // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
|
||||
return INFINITE;
|
||||
#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
|
||||
}
|
||||
|
||||
void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// detail/impl/win_iocp_serial_port_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -47,6 +47,7 @@ boost::system::error_code win_iocp_serial_port_service::open(
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = boost::asio::error::already_open;
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ boost::system::error_code win_iocp_serial_port_service::open(
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -76,21 +78,34 @@ boost::system::error_code win_iocp_serial_port_service::open(
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set some default serial port parameters. This implementation does not
|
||||
// support changing these, so they might as well be in a known state.
|
||||
// support changing all of these, so they might as well be in a known state.
|
||||
dcb.fBinary = TRUE; // Win32 only supports binary mode.
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fNull = FALSE; // Do not ignore NULL characters.
|
||||
dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
|
||||
dcb.BaudRate = CBR_9600; // 9600 baud by default
|
||||
dcb.ByteSize = 8; // 8 bit bytes
|
||||
dcb.fOutxCtsFlow = FALSE; // No flow control
|
||||
dcb.fOutxDsrFlow = FALSE;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fOutX = FALSE;
|
||||
dcb.fInX = FALSE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
dcb.fParity = FALSE; // No parity
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT; // One stop bit
|
||||
if (!::SetCommState(handle, &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -109,6 +124,7 @@ boost::system::error_code win_iocp_serial_port_service::open(
|
||||
::CloseHandle(handle);
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -133,6 +149,7 @@ boost::system::error_code win_iocp_serial_port_service::do_set_option(
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -144,6 +161,7 @@ boost::system::error_code win_iocp_serial_port_service::do_set_option(
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -166,6 +184,7 @@ boost::system::error_code win_iocp_serial_port_service::do_get_option(
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
BOOST_ASIO_ERROR_LOCATION(ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user