mirror of
https://github.com/Vita3K/ext-boost.git
synced 2024-11-26 23:10:28 +00:00
update boost to 1.78.
This commit is contained in:
parent
a021ff3878
commit
0009f49022
24
Jamroot
24
Jamroot
@ -144,9 +144,12 @@ import option ;
|
||||
import tools/boost\_install/boost-install ;
|
||||
|
||||
path-constant BOOST_ROOT : . ;
|
||||
constant BOOST_VERSION : 1.72.0 ;
|
||||
constant BOOST_VERSION : 1.78.0 ;
|
||||
constant BOOST_JAMROOT_MODULE : $(__name__) ;
|
||||
|
||||
# Allow subprojects to simply `import config : requires ;` to get access to the requires rule
|
||||
modules.poke : BOOST_BUILD_PATH : $(BOOST_ROOT)/libs/config/checks [ modules.peek : BOOST_BUILD_PATH ] ;
|
||||
|
||||
boostcpp.set-version $(BOOST_VERSION) ;
|
||||
|
||||
use-project /boost/architecture : libs/config/checks/architecture ;
|
||||
@ -210,18 +213,15 @@ rule handle-static-runtime ( properties * )
|
||||
# dangerous on Windows. Therefore, we disallow it. This might be drastic,
|
||||
# but it was disabled for a while without anybody complaining.
|
||||
|
||||
# For CW, static runtime is needed so that std::locale works.
|
||||
if <link>shared in $(properties) && <runtime-link>static in $(properties) &&
|
||||
! ( <toolset>cw in $(properties) )
|
||||
{
|
||||
if ! $(.shared-static-warning-emitted)
|
||||
{
|
||||
ECHO "warning: skipping configuration link=shared, runtime-link=static" ;
|
||||
ECHO "warning: this combination is either impossible or too dangerous" ;
|
||||
ECHO "warning: to be of any use" ;
|
||||
.shared-static-warning-emitted = 1 ;
|
||||
}
|
||||
local argv = [ modules.peek : ARGV ] ;
|
||||
|
||||
if <link>shared in $(properties)
|
||||
&& <runtime-link>static in $(properties)
|
||||
# For CW, static runtime is needed so that std::locale works.
|
||||
&& ! ( <toolset>cw in $(properties) )
|
||||
&& ! --allow-shared-static in $(argv)
|
||||
{
|
||||
boostcpp.emit-shared-static-warning ;
|
||||
return <build>no ;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Boost libraries - trimmed down for Vita3K
|
||||
|
||||
This is a subset of Boost v1.72.0 generated using the bcp tool. To get a list of boost modules guaranteed to exist, check the build script.
|
||||
This is a subset of Boost v1.78.0 generated using the bcp tool. To get a list of boost modules guaranteed to exist, check the build script.
|
||||
Adapted from [citra-emu/ext-boost](https://github.com/citra-emu/ext-boost).
|
||||
|
||||
## Updating this repo
|
||||
|
@ -65,7 +65,7 @@ namespace boost {
|
||||
template< typename T1, typename T2 >
|
||||
bool operator()( const T1& Arg1, const T2& Arg2 ) const
|
||||
{
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper(Arg1)==std::toupper(Arg2);
|
||||
#else
|
||||
return std::toupper<T1>(Arg1,m_Loc)==std::toupper<T2>(Arg2,m_Loc);
|
||||
@ -118,7 +118,7 @@ namespace boost {
|
||||
template< typename T1, typename T2 >
|
||||
bool operator()( const T1& Arg1, const T2& Arg2 ) const
|
||||
{
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper(Arg1)<std::toupper(Arg2);
|
||||
#else
|
||||
return std::toupper<T1>(Arg1,m_Loc)<std::toupper<T2>(Arg2,m_Loc);
|
||||
@ -171,7 +171,7 @@ namespace boost {
|
||||
template< typename T1, typename T2 >
|
||||
bool operator()( const T1& Arg1, const T2& Arg2 ) const
|
||||
{
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper(Arg1)<=std::toupper(Arg2);
|
||||
#else
|
||||
return std::toupper<T1>(Arg1,m_Loc)<=std::toupper<T2>(Arg2,m_Loc);
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <locale>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
|
||||
namespace boost {
|
||||
@ -40,7 +43,7 @@ namespace boost {
|
||||
// Operation
|
||||
CharT operator ()( CharT Ch ) const
|
||||
{
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::tolower( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
|
||||
#else
|
||||
return std::tolower<CharT>( Ch, *m_Loc );
|
||||
@ -62,7 +65,7 @@ namespace boost {
|
||||
// Operation
|
||||
CharT operator ()( CharT Ch ) const
|
||||
{
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
|
||||
#else
|
||||
return std::toupper<CharT>( Ch, *m_Loc );
|
||||
|
@ -13,10 +13,12 @@
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/distance.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/algorithm/string/predicate_facade.hpp>
|
||||
@ -45,7 +47,7 @@ namespace boost {
|
||||
return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
|
||||
}
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL)
|
||||
#if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x582) && !defined(_USE_OLD_RW_STL)
|
||||
template<>
|
||||
bool operator()( char const Ch ) const
|
||||
{
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <boost/algorithm/string/detail/find_format_store.hpp>
|
||||
#include <boost/algorithm/string/detail/replace_storage.hpp>
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
namespace detail {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
@ -127,8 +127,8 @@ namespace boost {
|
||||
if( boost::empty(m_Search) )
|
||||
return result_type( End, End );
|
||||
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
std::iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
|
||||
return findit( Begin, End, category() );
|
||||
}
|
||||
@ -344,9 +344,8 @@ namespace boost {
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
input_iterator_type It=Begin;
|
||||
for(
|
||||
unsigned int Index=0;
|
||||
Index<N && It!=End; ++Index,++It ) {};
|
||||
for( unsigned int Index=0; Index<N && It!=End; ++Index,++It )
|
||||
;
|
||||
|
||||
return result_type( Begin, It );
|
||||
}
|
||||
@ -375,8 +374,8 @@ namespace boost {
|
||||
ForwardIteratorT End,
|
||||
unsigned int N )
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
std::iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
|
||||
return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
|
||||
}
|
||||
@ -397,10 +396,12 @@ namespace boost {
|
||||
input_iterator_type It2=Begin;
|
||||
|
||||
// Advance It2 by N increments
|
||||
for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
|
||||
for( Index=0; Index<N && It2!=End; ++Index,++It2 )
|
||||
;
|
||||
|
||||
// Advance It, It2 to the end
|
||||
for(; It2!=End; ++It,++It2 ) {};
|
||||
for(; It2!=End; ++It,++It2 )
|
||||
;
|
||||
|
||||
return result_type( It, It2 );
|
||||
}
|
||||
@ -417,9 +418,8 @@ namespace boost {
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
input_iterator_type It=End;
|
||||
for(
|
||||
unsigned int Index=0;
|
||||
Index<N && It!=Begin; ++Index,--It ) {};
|
||||
for( unsigned int Index=0; Index<N && It!=Begin; ++Index,--It )
|
||||
;
|
||||
|
||||
return result_type( It, End );
|
||||
}
|
||||
@ -448,8 +448,8 @@ namespace boost {
|
||||
ForwardIteratorT End,
|
||||
unsigned int N )
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
std::iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
|
||||
return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace boost {
|
||||
m_Format(::boost::begin(Format), ::boost::end(Format)) {}
|
||||
|
||||
// Operation
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
|
||||
template<typename Range2T>
|
||||
result_type& operator()(const Range2T&)
|
||||
{
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define BOOST_STRING_TRIM_DETAIL_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
@ -80,8 +80,8 @@ namespace boost {
|
||||
ForwardIteratorT InEnd,
|
||||
PredicateT IsSpace )
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
std::iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
|
||||
return ::boost::algorithm::detail::trim_end_iter_select( InBegin, InEnd, IsSpace, category() );
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#define BOOST_STRING_FIND_FORMAT_HPP
|
||||
|
||||
#include <deque>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
@ -40,7 +39,7 @@ namespace boost {
|
||||
this substring and replace it in the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Finder A Finder object used to search for a match to be replaced
|
||||
|
@ -11,7 +11,6 @@
|
||||
#ifndef BOOST_STRING_FORMATTER_HPP
|
||||
#define BOOST_STRING_FORMATTER_HPP
|
||||
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/range/as_literal.hpp>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef BOOST_STRING_PREDICATE_HPP
|
||||
#define BOOST_STRING_PREDICATE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
@ -144,10 +145,10 @@ namespace boost {
|
||||
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
|
||||
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
range_const_iterator<Range1T>::type Iterator1T;
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<Iterator1T>::iterator_category category;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
std::iterator_traits<Iterator1T>::iterator_category category;
|
||||
|
||||
return detail::
|
||||
ends_with_iter_select(
|
||||
|
@ -10,7 +10,7 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
#if !defined(BOOST_NO_CXX11_STD_ALIGN) && !defined(BOOST_LIBSTDCXX_VERSION)
|
||||
#include <boost/align/detail/align_cxx11.hpp>
|
||||
#else
|
||||
#include <boost/align/detail/align.hpp>
|
||||
|
@ -18,12 +18,16 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_ALIGN_USE_ALLOCATE)
|
||||
#if defined(BOOST_ALIGN_USE_ALIGN)
|
||||
#include <boost/align/detail/aligned_alloc.hpp>
|
||||
#elif defined(BOOST_ALIGN_USE_NEW)
|
||||
#include <boost/align/detail/aligned_alloc_new.hpp>
|
||||
#elif defined(_MSC_VER) && !defined(UNDER_CE)
|
||||
#include <boost/align/detail/aligned_alloc_msvc.hpp>
|
||||
#elif defined(__MINGW32__) && (__MSVCRT_VERSION__ >= 0x0700)
|
||||
#include <boost/align/detail/aligned_alloc_msvc.hpp>
|
||||
#elif defined(__MINGW32__)
|
||||
#include <boost/align/detail/aligned_alloc_mingw.hpp>
|
||||
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
|
||||
#include <boost/align/detail/aligned_alloc_posix.hpp>
|
||||
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
|
@ -23,7 +23,7 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
#include <boost/align/detail/alignment_of_cxx11.hpp>
|
||||
#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
|
||||
#include <boost/align/detail/alignment_of_gcc.hpp>
|
||||
#elif defined(__CODEGEARC__)
|
||||
#elif defined(BOOST_CODEGEARC)
|
||||
#include <boost/align/detail/alignment_of_codegear.hpp>
|
||||
#elif defined(BOOST_CLANG)
|
||||
#include <boost/align/detail/alignment_of_clang.hpp>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2014-2016 Glen Joseph Fernandes
|
||||
Copyright 2014-2020 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
@ -18,14 +18,14 @@ inline void*
|
||||
align(std::size_t alignment, std::size_t size, void*& ptr,
|
||||
std::size_t& space)
|
||||
{
|
||||
BOOST_ASSERT(detail::is_alignment(alignment));
|
||||
BOOST_ASSERT(boost::alignment::detail::is_alignment(alignment));
|
||||
if (size <= space) {
|
||||
char* p = reinterpret_cast<char*>(~(alignment - 1) &
|
||||
(reinterpret_cast<std::size_t>(ptr) + alignment - 1));
|
||||
std::size_t n = space - (p - static_cast<char*>(ptr));
|
||||
if (size <= n) {
|
||||
std::size_t n = p - static_cast<char*>(ptr);
|
||||
if (n <= space - size) {
|
||||
ptr = p;
|
||||
space = n;
|
||||
space -= n;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
34
boost/align/detail/aligned_alloc_mingw.hpp
Normal file
34
boost/align/detail/aligned_alloc_mingw.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2020 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MINGW_HPP
|
||||
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MINGW_HPP
|
||||
|
||||
#include <boost/align/detail/is_alignment.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <malloc.h>
|
||||
|
||||
namespace boost {
|
||||
namespace alignment {
|
||||
|
||||
inline void*
|
||||
aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT(detail::is_alignment(alignment));
|
||||
return ::__mingw_aligned_malloc(size, alignment);
|
||||
}
|
||||
|
||||
inline void
|
||||
aligned_free(void* ptr) BOOST_NOEXCEPT
|
||||
{
|
||||
::__mingw_aligned_free(ptr);
|
||||
}
|
||||
|
||||
} /* alignment */
|
||||
} /* boost */
|
||||
|
||||
#endif
|
52
boost/align/detail/aligned_alloc_new.hpp
Normal file
52
boost/align/detail/aligned_alloc_new.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2014-2015 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_NEW_HPP
|
||||
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_NEW_HPP
|
||||
|
||||
#include <boost/align/detail/is_alignment.hpp>
|
||||
#include <boost/align/align.hpp>
|
||||
#include <boost/align/alignment_of.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <new>
|
||||
|
||||
namespace boost {
|
||||
namespace alignment {
|
||||
|
||||
inline void*
|
||||
aligned_alloc(std::size_t alignment, std::size_t size) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT(detail::is_alignment(alignment));
|
||||
enum {
|
||||
N = alignment_of<void*>::value
|
||||
};
|
||||
if (alignment < N) {
|
||||
alignment = N;
|
||||
}
|
||||
std::size_t n = size + alignment - N;
|
||||
void* p = ::operator new(sizeof(void*) + n, std::nothrow);
|
||||
if (p) {
|
||||
void* r = static_cast<char*>(p) + sizeof(void*);
|
||||
(void)boost::alignment::align(alignment, size, r, n);
|
||||
*(static_cast<void**>(r) - 1) = p;
|
||||
p = r;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
inline void
|
||||
aligned_free(void* ptr) BOOST_NOEXCEPT
|
||||
{
|
||||
if (ptr) {
|
||||
::operator delete(*(static_cast<void**>(ptr) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
} /* alignment */
|
||||
} /* boost */
|
||||
|
||||
#endif
|
@ -3,20 +3,20 @@
|
||||
#ifndef BOOST_ANY_INCLUDED
|
||||
#define BOOST_ANY_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// what: variant type boost::any
|
||||
// who: contributed by Kevlin Henney,
|
||||
// with features contributed and bugs found by
|
||||
// Antony Polukhin, Ed Brey, Mark Rodgers,
|
||||
// Antony Polukhin, Ed Brey, Mark Rodgers,
|
||||
// Peter Dimov, and James Curran
|
||||
// when: July 2001, April 2013 - 2019
|
||||
// when: July 2001, April 2013 - 2020
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/any/bad_any_cast.hpp>
|
||||
#include <boost/any/fwd.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
@ -29,7 +29,6 @@
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
|
||||
namespace boost
|
||||
@ -49,6 +48,10 @@ namespace boost
|
||||
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
|
||||
>(value))
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
!anys::detail::is_basic_any<ValueType>::value,
|
||||
"boost::any shall not be constructed from boost::anys::basic_any"
|
||||
);
|
||||
}
|
||||
|
||||
any(const any & other)
|
||||
@ -71,6 +74,10 @@ namespace boost
|
||||
, typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&`
|
||||
: content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value)))
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
!anys::detail::is_basic_any<typename boost::decay<ValueType>::type>::value,
|
||||
"boost::any shall not be constructed from boost::anys::basic_any"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -83,7 +90,9 @@ namespace boost
|
||||
|
||||
any & swap(any & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
std::swap(content, rhs.content);
|
||||
placeholder* tmp = content;
|
||||
content = rhs.content;
|
||||
rhs.content = tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -92,6 +101,10 @@ namespace boost
|
||||
template<typename ValueType>
|
||||
any & operator=(const ValueType & rhs)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
!anys::detail::is_basic_any<ValueType>::value,
|
||||
"boost::anys::basic_any shall not be assigned into boost::any"
|
||||
);
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
@ -102,7 +115,7 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
#else
|
||||
any & operator=(const any& rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
@ -121,6 +134,10 @@ namespace boost
|
||||
template <class ValueType>
|
||||
any & operator=(ValueType&& rhs)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
!anys::detail::is_basic_any<typename boost::decay<ValueType>::type>::value,
|
||||
"boost::anys::basic_any shall not be assigned into boost::any"
|
||||
);
|
||||
any(static_cast<ValueType&&>(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
@ -187,12 +204,12 @@ namespace boost
|
||||
#endif
|
||||
public: // queries
|
||||
|
||||
virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
|
||||
const boost::typeindex::type_info& type() const BOOST_NOEXCEPT BOOST_OVERRIDE
|
||||
{
|
||||
return boost::typeindex::type_id<ValueType>().type_info();
|
||||
}
|
||||
|
||||
virtual placeholder * clone() const
|
||||
placeholder * clone() const BOOST_OVERRIDE
|
||||
{
|
||||
return new holder(held);
|
||||
}
|
||||
@ -224,27 +241,12 @@ namespace boost
|
||||
placeholder * content;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE bad_any_cast :
|
||||
#ifndef BOOST_NO_RTTI
|
||||
public std::bad_cast
|
||||
#else
|
||||
public std::exception
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return "boost::bad_any_cast: "
|
||||
"failed conversion using boost::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
@ -271,9 +273,9 @@ namespace boost
|
||||
if(!result)
|
||||
boost::throw_exception(bad_any_cast());
|
||||
|
||||
// Attempt to avoid construction of a temporary object in cases when
|
||||
// Attempt to avoid construction of a temporary object in cases when
|
||||
// `ValueType` is not a reference. Example:
|
||||
// `static_cast<std::string>(*result);`
|
||||
// `static_cast<std::string>(*result);`
|
||||
// which is equal to `std::string(*result);`
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::conditional<
|
||||
boost::is_reference<ValueType>::value,
|
||||
@ -305,7 +307,7 @@ namespace boost
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/
|
||||
|| boost::is_const< typename boost::remove_reference<ValueType>::type >::value,
|
||||
"boost::any_cast shall not be used for getting nonconst references to temporary objects"
|
||||
"boost::any_cast shall not be used for getting nonconst references to temporary objects"
|
||||
);
|
||||
return any_cast<ValueType>(operand);
|
||||
}
|
||||
@ -333,7 +335,7 @@ namespace boost
|
||||
}
|
||||
|
||||
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
||||
// Copyright Antony Polukhin, 2013-2019.
|
||||
// Copyright Antony Polukhin, 2013-2021.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
|
43
boost/any/bad_any_cast.hpp
Normal file
43
boost/any/bad_any_cast.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright Antony Polukhin, 2020-2021.
|
||||
//
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org/libs/any for Documentation.
|
||||
|
||||
#ifndef BOOST_ANYS_BAD_ANY_CAST_HPP_INCLUDED
|
||||
#define BOOST_ANYS_BAD_ANY_CAST_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_SYMBOL_VISIBLE bad_any_cast :
|
||||
#ifndef BOOST_NO_RTTI
|
||||
public std::bad_cast
|
||||
#else
|
||||
public std::exception
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
|
||||
{
|
||||
return "boost::bad_any_cast: "
|
||||
"failed conversion using boost::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // #ifndef BOOST_ANYS_BAD_ANY_CAST_HPP_INCLUDED
|
40
boost/any/fwd.hpp
Normal file
40
boost/any/fwd.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright Antony Polukhin, 2021.
|
||||
//
|
||||
// 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)
|
||||
|
||||
// Contributed by Ruslan Arutyunyan
|
||||
#ifndef BOOST_ANY_ANYS_FWD_HPP
|
||||
#define BOOST_ANY_ANYS_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class any;
|
||||
|
||||
namespace anys {
|
||||
|
||||
template<std::size_t OptimizeForSize = sizeof(void*), std::size_t OptimizeForAlignment = boost::alignment_of<void*>::value>
|
||||
class basic_any;
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
struct is_basic_any: public false_type {};
|
||||
|
||||
|
||||
template<std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
|
||||
struct is_basic_any<boost::anys::basic_any<OptimizeForSize, OptimizeForAlignment> > : public true_type {};
|
||||
} // namespace detail
|
||||
|
||||
} // namespace anys
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_ANY_ANYS_FWD_HPP
|
@ -9,7 +9,7 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// archive/archive_exception.hpp:
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// Use, modification and distribution is subject to 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,16 +20,16 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/archive/detail/decl.hpp>
|
||||
|
||||
// note: the only reason this is in here is that windows header
|
||||
// includes #define exception_code _exception_code (arrrgghhhh!).
|
||||
// the most expedient way to address this is be sure that this
|
||||
// header is always included whenever this header file is included.
|
||||
#if defined(BOOST_WINDOWS)
|
||||
#include <excpt.h>
|
||||
#endif
|
||||
#if defined(BOOST_WINDOWS)
|
||||
#include <excpt.h>
|
||||
#endif
|
||||
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
@ -39,7 +39,7 @@ namespace archive {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// exceptions thrown by archives
|
||||
//
|
||||
class BOOST_SYMBOL_VISIBLE archive_exception :
|
||||
class BOOST_SYMBOL_VISIBLE archive_exception :
|
||||
public virtual std::exception
|
||||
{
|
||||
private:
|
||||
@ -52,7 +52,7 @@ protected:
|
||||
public:
|
||||
typedef enum {
|
||||
no_exception, // initialized without code
|
||||
other_exception, // any excepton not listed below
|
||||
other_exception, // any exception not listed below
|
||||
unregistered_class, // attempt to serialize a pointer of
|
||||
// an unregistered class
|
||||
invalid_signature, // first line of archive does not contain
|
||||
@ -61,9 +61,9 @@ public:
|
||||
// subsequent to this one
|
||||
pointer_conflict, // an attempt has been made to directly
|
||||
// serialize an object which has
|
||||
// already been serialized through a pointer.
|
||||
// Were this permitted, the archive load would result
|
||||
// in the creation of an extra copy of the obect.
|
||||
// already been serialized through a pointer.
|
||||
// Were this permitted, the archive load would result
|
||||
// in the creation of an extra copy of the object.
|
||||
incompatible_native_format, // attempt to read native binary format
|
||||
// on incompatible platform
|
||||
array_size_too_short,// array being loaded doesn't fit in array allocated
|
||||
@ -71,9 +71,9 @@ public:
|
||||
invalid_class_name, // class name greater than the maximum permitted.
|
||||
// most likely a corrupted archive or an attempt
|
||||
// to insert virus via buffer overrun method.
|
||||
unregistered_cast, // base - derived relationship not registered with
|
||||
unregistered_cast, // base - derived relationship not registered with
|
||||
// void_cast_register
|
||||
unsupported_class_version, // type saved with a version # greater than the
|
||||
unsupported_class_version, // type saved with a version # greater than the
|
||||
// one used by the program. This indicates that the program
|
||||
// needs to be rebuilt.
|
||||
multiple_code_instantiation, // code for implementing serialization for some
|
||||
@ -83,13 +83,13 @@ public:
|
||||
exception_code code;
|
||||
|
||||
BOOST_ARCHIVE_DECL archive_exception(
|
||||
exception_code c,
|
||||
exception_code c,
|
||||
const char * e1 = NULL,
|
||||
const char * e2 = NULL
|
||||
) BOOST_NOEXCEPT;
|
||||
BOOST_ARCHIVE_DECL archive_exception(archive_exception const &) BOOST_NOEXCEPT ;
|
||||
virtual BOOST_ARCHIVE_DECL ~archive_exception() BOOST_NOEXCEPT_OR_NOTHROW ;
|
||||
virtual BOOST_ARCHIVE_DECL const char * what() const BOOST_NOEXCEPT_OR_NOTHROW ;
|
||||
BOOST_ARCHIVE_DECL archive_exception(archive_exception const &) BOOST_NOEXCEPT;
|
||||
BOOST_ARCHIVE_DECL ~archive_exception() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE;
|
||||
BOOST_ARCHIVE_DECL const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE;
|
||||
};
|
||||
|
||||
}// namespace archive
|
||||
|
@ -1,7 +1,7 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// abi_prefix.hpp
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// Use, modification and distribution is subject to 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,7 +1,7 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// abi_suffix.hpp
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// Use, modification and distribution is subject to 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,10 +1,10 @@
|
||||
#ifndef BOOST_ARCHIVE_DETAIL_DECL_HPP
|
||||
#define BOOST_ARCHIVE_DETAIL_DECL_HPP
|
||||
#define BOOST_ARCHIVE_DETAIL_DECL_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8
|
||||
// decl.hpp
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
// See library home page at http://www.boost.org/libs/serialization
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// This header implements separate compilation features as described in
|
||||
// http://www.boost.org/more/separate_compilation.html
|
||||
|
@ -41,13 +41,12 @@
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
|
||||
// Handles broken standard libraries better than <iterator>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
305
boost/asio/any_io_executor.hpp
Normal file
305
boost/asio/any_io_executor.hpp
Normal file
@ -0,0 +1,305 @@
|
||||
//
|
||||
// any_io_executor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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_ANY_IO_EXECUTOR_HPP
|
||||
#define BOOST_ASIO_ANY_IO_EXECUTOR_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_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
# include <boost/asio/executor.hpp>
|
||||
#else // defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
# include <boost/asio/execution.hpp>
|
||||
# include <boost/asio/execution_context.hpp>
|
||||
#endif // defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
typedef executor any_io_executor;
|
||||
|
||||
#else // defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
/// Polymorphic executor type for use with I/O objects.
|
||||
/**
|
||||
* The @c any_io_executor type is a polymorphic executor that supports the set
|
||||
* of properties required by I/O objects. It is defined as the
|
||||
* execution::any_executor class template parameterised as follows:
|
||||
* @code execution::any_executor<
|
||||
* execution::context_as_t<execution_context&>,
|
||||
* execution::blocking_t::never_t,
|
||||
* execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||
* execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||
* execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||
* execution::prefer_only<execution::relationship_t::fork_t>,
|
||||
* execution::prefer_only<execution::relationship_t::continuation_t>
|
||||
* > @endcode
|
||||
*/
|
||||
class any_io_executor :
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
public execution::any_executor<...>
|
||||
#else // defined(GENERATING_DOCUMENTATION)
|
||||
public execution::any_executor<
|
||||
execution::context_as_t<execution_context&>,
|
||||
execution::blocking_t::never_t,
|
||||
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||
>
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
{
|
||||
public:
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
typedef execution::any_executor<
|
||||
execution::context_as_t<execution_context&>,
|
||||
execution::blocking_t::never_t,
|
||||
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||
> base_type;
|
||||
|
||||
typedef void supportable_properties_type(
|
||||
execution::context_as_t<execution_context&>,
|
||||
execution::blocking_t::never_t,
|
||||
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||
);
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Default constructor.
|
||||
BOOST_ASIO_DECL any_io_executor() BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
/// Construct in an empty state. Equivalent effects to default constructor.
|
||||
BOOST_ASIO_DECL any_io_executor(nullptr_t) BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
/// Copy constructor.
|
||||
BOOST_ASIO_DECL any_io_executor(const any_io_executor& e) BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move constructor.
|
||||
BOOST_ASIO_DECL any_io_executor(any_io_executor&& e) BOOST_ASIO_NOEXCEPT;
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Construct to point to the same target as another any_executor.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
template <class... OtherSupportableProperties>
|
||||
any_io_executor(execution::any_executor<OtherSupportableProperties...> e);
|
||||
#else // defined(GENERATING_DOCUMENTATION)
|
||||
template <typename OtherAnyExecutor>
|
||||
any_io_executor(OtherAnyExecutor e,
|
||||
typename constraint<
|
||||
conditional<
|
||||
!is_same<OtherAnyExecutor, any_io_executor>::value
|
||||
&& is_base_of<execution::detail::any_executor_base,
|
||||
OtherAnyExecutor>::value,
|
||||
typename execution::detail::supportable_properties<
|
||||
0, supportable_properties_type>::template
|
||||
is_valid_target<OtherAnyExecutor>,
|
||||
false_type
|
||||
>::type::value
|
||||
>::type = 0)
|
||||
: base_type(BOOST_ASIO_MOVE_CAST(OtherAnyExecutor)(e))
|
||||
{
|
||||
}
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Construct a polymorphic wrapper for the specified executor.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
|
||||
any_io_executor(Executor e);
|
||||
#else // defined(GENERATING_DOCUMENTATION)
|
||||
template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
|
||||
any_io_executor(Executor e,
|
||||
typename constraint<
|
||||
conditional<
|
||||
!is_same<Executor, any_io_executor>::value
|
||||
&& !is_base_of<execution::detail::any_executor_base,
|
||||
Executor>::value,
|
||||
execution::detail::is_valid_target_executor<
|
||||
Executor, supportable_properties_type>,
|
||||
false_type
|
||||
>::type::value
|
||||
>::type = 0)
|
||||
: base_type(BOOST_ASIO_MOVE_CAST(Executor)(e))
|
||||
{
|
||||
}
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Assignment operator.
|
||||
BOOST_ASIO_DECL any_io_executor& operator=(
|
||||
const any_io_executor& e) BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move assignment operator.
|
||||
BOOST_ASIO_DECL any_io_executor& operator=(
|
||||
any_io_executor&& e) BOOST_ASIO_NOEXCEPT;
|
||||
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Assignment operator that sets the polymorphic wrapper to the empty state.
|
||||
BOOST_ASIO_DECL any_io_executor& operator=(nullptr_t);
|
||||
|
||||
/// Destructor.
|
||||
BOOST_ASIO_DECL ~any_io_executor();
|
||||
|
||||
/// Swap targets with another polymorphic wrapper.
|
||||
BOOST_ASIO_DECL void swap(any_io_executor& other) BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
/// Obtain a polymorphic wrapper with the specified property.
|
||||
/**
|
||||
* Do not call this function directly. It is intended for use with the
|
||||
* boost::asio::require and boost::asio::prefer customisation points.
|
||||
*
|
||||
* For example:
|
||||
* @code any_io_executor ex = ...;
|
||||
* auto ex2 = boost::asio::require(ex, execution::blocking.possibly); @endcode
|
||||
*/
|
||||
template <typename Property>
|
||||
any_io_executor require(const Property& p,
|
||||
typename constraint<
|
||||
traits::require_member<const base_type&, const Property&>::is_valid
|
||||
>::type = 0) const
|
||||
{
|
||||
return static_cast<const base_type&>(*this).require(p);
|
||||
}
|
||||
|
||||
/// Obtain a polymorphic wrapper with the specified property.
|
||||
/**
|
||||
* Do not call this function directly. It is intended for use with the
|
||||
* boost::asio::prefer customisation point.
|
||||
*
|
||||
* For example:
|
||||
* @code any_io_executor ex = ...;
|
||||
* auto ex2 = boost::asio::prefer(ex, execution::blocking.possibly); @endcode
|
||||
*/
|
||||
template <typename Property>
|
||||
any_io_executor prefer(const Property& p,
|
||||
typename constraint<
|
||||
traits::prefer_member<const base_type&, const Property&>::is_valid
|
||||
>::type = 0) const
|
||||
{
|
||||
return static_cast<const base_type&>(*this).prefer(p);
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::require(
|
||||
const execution::blocking_t::never_t&, int) const;
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||
const execution::blocking_t::possibly_t&, int) const;
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||
const execution::outstanding_work_t::tracked_t&, int) const;
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||
const execution::outstanding_work_t::untracked_t&, int) const;
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||
const execution::relationship_t::fork_t&, int) const;
|
||||
|
||||
template <>
|
||||
BOOST_ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||
const execution::relationship_t::continuation_t&, int) const;
|
||||
|
||||
namespace traits {
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
||||
|
||||
template <>
|
||||
struct equality_comparable<any_io_executor>
|
||||
{
|
||||
static const bool is_valid = true;
|
||||
static const bool is_noexcept = true;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
||||
|
||||
template <typename F>
|
||||
struct execute_member<any_io_executor, F>
|
||||
{
|
||||
static const bool is_valid = true;
|
||||
static const bool is_noexcept = false;
|
||||
typedef void result_type;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
||||
|
||||
template <typename Prop>
|
||||
struct query_member<any_io_executor, Prop> :
|
||||
query_member<any_io_executor::base_type, Prop>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
||||
|
||||
template <typename Prop>
|
||||
struct require_member<any_io_executor, Prop> :
|
||||
require_member<any_io_executor::base_type, Prop>
|
||||
{
|
||||
typedef any_io_executor result_type;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
||||
|
||||
#if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
||||
|
||||
template <typename Prop>
|
||||
struct prefer_member<any_io_executor, Prop> :
|
||||
prefer_member<any_io_executor::base_type, Prop>
|
||||
{
|
||||
typedef any_io_executor result_type;
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
||||
|
||||
} // namespace traits
|
||||
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#endif // defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HEADER_ONLY) \
|
||||
&& !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
# include <boost/asio/impl/any_io_executor.ipp>
|
||||
#endif // defined(BOOST_ASIO_HEADER_ONLY)
|
||||
// && !defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||
|
||||
#endif // BOOST_ASIO_ANY_IO_EXECUTOR_HPP
|
@ -2,7 +2,7 @@
|
||||
// associated_allocator.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,21 +17,33 @@
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <memory>
|
||||
#include <boost/asio/associator.hpp>
|
||||
#include <boost/asio/detail/functional.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
template <typename T, typename Allocator>
|
||||
struct associated_allocator;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename>
|
||||
struct associated_allocator_check
|
||||
template <typename T, typename = void>
|
||||
struct has_allocator_type : false_type
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename = void>
|
||||
template <typename T>
|
||||
struct has_allocator_type<T,
|
||||
typename void_type<typename T::executor_type>::type>
|
||||
: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename = void, typename = void>
|
||||
struct associated_allocator_impl
|
||||
{
|
||||
typedef E type;
|
||||
@ -44,7 +56,7 @@ struct associated_allocator_impl
|
||||
|
||||
template <typename T, typename E>
|
||||
struct associated_allocator_impl<T, E,
|
||||
typename associated_allocator_check<typename T::allocator_type>::type>
|
||||
typename void_type<typename T::allocator_type>::type>
|
||||
{
|
||||
typedef typename T::allocator_type type;
|
||||
|
||||
@ -54,6 +66,17 @@ struct associated_allocator_impl<T, E,
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct associated_allocator_impl<T, E,
|
||||
typename enable_if<
|
||||
!has_allocator_type<T>::value
|
||||
>::type,
|
||||
typename void_type<
|
||||
typename associator<associated_allocator, T, E>::type
|
||||
>::type> : associator<associated_allocator, T, E>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Traits type used to obtain the allocator associated with an object.
|
||||
@ -125,6 +148,29 @@ using associated_allocator_t
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Specialisation of associated_allocator for @c std::reference_wrapper.
|
||||
template <typename T, typename Allocator>
|
||||
struct associated_allocator<reference_wrapper<T>, Allocator>
|
||||
{
|
||||
/// Forwards @c type to the associator specialisation for the unwrapped type
|
||||
/// @c T.
|
||||
typedef typename associated_allocator<T, Allocator>::type type;
|
||||
|
||||
/// Forwards the request to get the allocator to the associator specialisation
|
||||
/// for the unwrapped type @c T.
|
||||
static type get(reference_wrapper<T> t,
|
||||
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<T, Allocator>::get(t.get(), a);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
|
179
boost/asio/associated_cancellation_slot.hpp
Normal file
179
boost/asio/associated_cancellation_slot.hpp
Normal file
@ -0,0 +1,179 @@
|
||||
//
|
||||
// associated_cancellation_slot.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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_ASSOCIATED_CANCELLATION_SLOT_HPP
|
||||
#define BOOST_ASIO_ASSOCIATED_CANCELLATION_SLOT_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/associator.hpp>
|
||||
#include <boost/asio/cancellation_signal.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
template <typename T, typename CancellationSlot>
|
||||
struct associated_cancellation_slot;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct has_cancellation_slot_type : false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_cancellation_slot_type<T,
|
||||
typename void_type<typename T::cancellation_slot_type>::type>
|
||||
: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename S, typename = void, typename = void>
|
||||
struct associated_cancellation_slot_impl
|
||||
{
|
||||
typedef void asio_associated_cancellation_slot_is_unspecialised;
|
||||
|
||||
typedef S type;
|
||||
|
||||
static type get(const T&, const S& s = S()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename S>
|
||||
struct associated_cancellation_slot_impl<T, S,
|
||||
typename void_type<typename T::cancellation_slot_type>::type>
|
||||
{
|
||||
typedef typename T::cancellation_slot_type type;
|
||||
|
||||
static type get(const T& t, const S& = S()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return t.get_cancellation_slot();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename S>
|
||||
struct associated_cancellation_slot_impl<T, S,
|
||||
typename enable_if<
|
||||
!has_cancellation_slot_type<T>::value
|
||||
>::type,
|
||||
typename void_type<
|
||||
typename associator<associated_cancellation_slot, T, S>::type
|
||||
>::type> : associator<associated_cancellation_slot, T, S>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Traits type used to obtain the cancellation_slot associated with an object.
|
||||
/**
|
||||
* A program may specialise this traits type if the @c T template parameter in
|
||||
* the specialisation is a user-defined type. The template parameter @c
|
||||
* CancellationSlot shall be a type meeting the CancellationSlot requirements.
|
||||
*
|
||||
* Specialisations shall meet the following requirements, where @c t is a const
|
||||
* reference to an object of type @c T, and @c s is an object of type @c
|
||||
* CancellationSlot.
|
||||
*
|
||||
* @li Provide a nested typedef @c type that identifies a type meeting the
|
||||
* CancellationSlot requirements.
|
||||
*
|
||||
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||
* get(t) and with return type @c type.
|
||||
*
|
||||
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||
* get(t,s) and with return type @c type.
|
||||
*/
|
||||
template <typename T, typename CancellationSlot = cancellation_slot>
|
||||
struct associated_cancellation_slot
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
: detail::associated_cancellation_slot_impl<T, CancellationSlot>
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
{
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/// If @c T has a nested type @c cancellation_slot_type,
|
||||
/// <tt>T::cancellation_slot_type</tt>. Otherwise
|
||||
/// @c CancellationSlot.
|
||||
typedef see_below type;
|
||||
|
||||
/// If @c T has a nested type @c cancellation_slot_type, returns
|
||||
/// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s.
|
||||
static type get(const T& t,
|
||||
const CancellationSlot& s = CancellationSlot()) BOOST_ASIO_NOEXCEPT;
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
};
|
||||
|
||||
/// Helper function to obtain an object's associated cancellation_slot.
|
||||
/**
|
||||
* @returns <tt>associated_cancellation_slot<T>::get(t)</tt>
|
||||
*/
|
||||
template <typename T>
|
||||
inline typename associated_cancellation_slot<T>::type
|
||||
get_associated_cancellation_slot(const T& t) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_cancellation_slot<T>::get(t);
|
||||
}
|
||||
|
||||
/// Helper function to obtain an object's associated cancellation_slot.
|
||||
/**
|
||||
* @returns <tt>associated_cancellation_slot<T,
|
||||
* CancellationSlot>::get(t, st)</tt>
|
||||
*/
|
||||
template <typename T, typename CancellationSlot>
|
||||
inline typename associated_cancellation_slot<T, CancellationSlot>::type
|
||||
get_associated_cancellation_slot(const T& t,
|
||||
const CancellationSlot& st) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_cancellation_slot<T, CancellationSlot>::get(t, st);
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
|
||||
|
||||
template <typename T, typename CancellationSlot = cancellation_slot>
|
||||
using associated_cancellation_slot_t =
|
||||
typename associated_cancellation_slot<T, CancellationSlot>::type;
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename S, typename = void>
|
||||
struct associated_cancellation_slot_forwarding_base
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename S>
|
||||
struct associated_cancellation_slot_forwarding_base<T, S,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
typename associated_cancellation_slot<T,
|
||||
S>::asio_associated_cancellation_slot_is_unspecialised,
|
||||
void
|
||||
>::value
|
||||
>::type>
|
||||
{
|
||||
typedef void asio_associated_cancellation_slot_is_unspecialised;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
|
@ -2,7 +2,7 @@
|
||||
// associated_executor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,7 +16,10 @@
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/associator.hpp>
|
||||
#include <boost/asio/detail/functional.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
#include <boost/asio/execution/executor.hpp>
|
||||
#include <boost/asio/is_executor.hpp>
|
||||
#include <boost/asio/system_executor.hpp>
|
||||
|
||||
@ -24,20 +27,32 @@
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
template <typename T, typename Executor>
|
||||
struct associated_executor;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename>
|
||||
struct associated_executor_check
|
||||
template <typename T, typename = void>
|
||||
struct has_executor_type : false_type
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename = void>
|
||||
template <typename T>
|
||||
struct has_executor_type<T,
|
||||
typename void_type<typename T::executor_type>::type>
|
||||
: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename = void, typename = void>
|
||||
struct associated_executor_impl
|
||||
{
|
||||
typedef void asio_associated_executor_is_unspecialised;
|
||||
|
||||
typedef E type;
|
||||
|
||||
static type get(const T&, const E& e) BOOST_ASIO_NOEXCEPT
|
||||
static type get(const T&, const E& e = E()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return e;
|
||||
}
|
||||
@ -45,16 +60,27 @@ struct associated_executor_impl
|
||||
|
||||
template <typename T, typename E>
|
||||
struct associated_executor_impl<T, E,
|
||||
typename associated_executor_check<typename T::executor_type>::type>
|
||||
typename void_type<typename T::executor_type>::type>
|
||||
{
|
||||
typedef typename T::executor_type type;
|
||||
|
||||
static type get(const T& t, const E&) BOOST_ASIO_NOEXCEPT
|
||||
static type get(const T& t, const E& = E()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return t.get_executor();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct associated_executor_impl<T, E,
|
||||
typename enable_if<
|
||||
!has_executor_type<T>::value
|
||||
>::type,
|
||||
typename void_type<
|
||||
typename associator<associated_executor, T, E>::type
|
||||
>::type> : associator<associated_executor, T, E>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Traits type used to obtain the executor associated with an object.
|
||||
@ -78,22 +104,20 @@ struct associated_executor_impl<T, E,
|
||||
*/
|
||||
template <typename T, typename Executor = system_executor>
|
||||
struct associated_executor
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
: detail::associated_executor_impl<T, Executor>
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
{
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
|
||||
/// Otherwise @c Executor.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef see_below type;
|
||||
#else // defined(GENERATING_DOCUMENTATION)
|
||||
typedef typename detail::associated_executor_impl<T, Executor>::type type;
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// If @c T has a nested type @c executor_type, returns
|
||||
/// <tt>t.get_executor()</tt>. Otherwise returns @c ex.
|
||||
static type get(const T& t,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return detail::associated_executor_impl<T, Executor>::get(t, ex);
|
||||
}
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT;
|
||||
#endif // defined(GENERATING_DOCUMENTATION)
|
||||
};
|
||||
|
||||
/// Helper function to obtain an object's associated executor.
|
||||
@ -114,8 +138,9 @@ get_associated_executor(const T& t) BOOST_ASIO_NOEXCEPT
|
||||
template <typename T, typename Executor>
|
||||
inline typename associated_executor<T, Executor>::type
|
||||
get_associated_executor(const T& t, const Executor& ex,
|
||||
typename enable_if<is_executor<
|
||||
Executor>::value>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
typename constraint<
|
||||
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<T, Executor>::get(t, ex);
|
||||
}
|
||||
@ -129,8 +154,8 @@ template <typename T, typename ExecutionContext>
|
||||
inline typename associated_executor<T,
|
||||
typename ExecutionContext::executor_type>::type
|
||||
get_associated_executor(const T& t, ExecutionContext& ctx,
|
||||
typename enable_if<is_convertible<ExecutionContext&,
|
||||
execution_context&>::value>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
typename constraint<is_convertible<ExecutionContext&,
|
||||
execution_context&>::value>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<T,
|
||||
typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
|
||||
@ -143,6 +168,54 @@ using associated_executor_t = typename associated_executor<T, Executor>::type;
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename E, typename = void>
|
||||
struct associated_executor_forwarding_base
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct associated_executor_forwarding_base<T, E,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
typename associated_executor<T,
|
||||
E>::asio_associated_executor_is_unspecialised,
|
||||
void
|
||||
>::value
|
||||
>::type>
|
||||
{
|
||||
typedef void asio_associated_executor_is_unspecialised;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Specialisation of associated_executor for @c std::reference_wrapper.
|
||||
template <typename T, typename Executor>
|
||||
struct associated_executor<reference_wrapper<T>, Executor>
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
: detail::associated_executor_forwarding_base<T, Executor>
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
{
|
||||
/// Forwards @c type to the associator specialisation for the unwrapped type
|
||||
/// @c T.
|
||||
typedef typename associated_executor<T, Executor>::type type;
|
||||
|
||||
/// Forwards the request to get the executor to the associator specialisation
|
||||
/// for the unwrapped type @c T.
|
||||
static type get(reference_wrapper<T> t,
|
||||
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<T, Executor>::get(t.get(), ex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
|
37
boost/asio/associator.hpp
Normal file
37
boost/asio/associator.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// associator.hpp
|
||||
// ~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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_ASSOCIATOR_HPP
|
||||
#define BOOST_ASIO_ASSOCIATOR_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/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
/// Used to generically specialise associators for a type.
|
||||
template <template <typename, typename> class Associator,
|
||||
typename T, typename DefaultCandidate>
|
||||
struct associator
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_ASSOCIATOR_HPP
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
// basic_datagram_socket.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,7 +33,7 @@ namespace asio {
|
||||
#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
template <typename Protocol, typename Executor = any_io_executor>
|
||||
class basic_datagram_socket;
|
||||
|
||||
#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
|
||||
@ -46,6 +46,13 @@ class basic_datagram_socket;
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* Synchronous @c send, @c send_to, @c receive, @c receive_from, and @c connect
|
||||
* operations are thread safe with respect to each other, if the underlying
|
||||
* operating system calls are also thread safe. This means that it is permitted
|
||||
* to perform concurrent calls to these synchronous operations on a single
|
||||
* socket object. Other synchronous operations, such as @c open or @c close, are
|
||||
* not thread safe.
|
||||
*/
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_datagram_socket
|
||||
@ -101,9 +108,9 @@ public:
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_datagram_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
>::type = 0)
|
||||
: basic_socket<Protocol, Executor>(context)
|
||||
{
|
||||
}
|
||||
@ -139,9 +146,10 @@ public:
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||
defaulted_constraint
|
||||
>::type = defaulted_constraint())
|
||||
: basic_socket<Protocol, Executor>(context, protocol)
|
||||
{
|
||||
}
|
||||
@ -185,9 +193,9 @@ public:
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
>::type = 0)
|
||||
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||
{
|
||||
}
|
||||
@ -230,9 +238,9 @@ public:
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
>::type = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
@ -286,10 +294,10 @@ public:
|
||||
*/
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
>::type = 0)
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
@ -308,7 +316,7 @@ public:
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_datagram_socket&
|
||||
@ -447,6 +455,16 @@ public:
|
||||
* See the @ref buffer documentation for information on sending multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -491,6 +509,16 @@ public:
|
||||
* @note The async_send operation can only be used with a connected socket.
|
||||
* Use the async_send_to function to send data on an unconnected datagram
|
||||
* socket.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -632,6 +660,16 @@ public:
|
||||
* See the @ref buffer documentation for information on sending multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -676,6 +714,16 @@ public:
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using boost::asio::post().
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename ConstBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -817,6 +865,16 @@ public:
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -861,6 +919,16 @@ public:
|
||||
* @note The async_receive operation can only be used with a connected socket.
|
||||
* Use the async_receive_from function to receive data on an unconnected
|
||||
* datagram socket.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -1002,6 +1070,16 @@ public:
|
||||
* See the @ref buffer documentation for information on receiving into
|
||||
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -1048,6 +1126,16 @@ public:
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using boost::asio::post().
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
|
||||
@ -1067,6 +1155,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
basic_datagram_socket(const basic_datagram_socket&) BOOST_ASIO_DELETED;
|
||||
basic_datagram_socket& operator=(
|
||||
const basic_datagram_socket&) BOOST_ASIO_DELETED;
|
||||
|
||||
class initiate_async_send
|
||||
{
|
||||
public:
|
||||
@ -1094,7 +1187,7 @@ private:
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1127,8 +1220,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send_to(
|
||||
self_->impl_.get_implementation(), buffers, destination, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, destination,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1162,7 +1255,7 @@ private:
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1195,8 +1288,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive_from(
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -2,7 +2,7 @@
|
||||
// basic_socket.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,6 +15,7 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/detail/handler_type_requirements.hpp>
|
||||
@ -24,7 +25,6 @@
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/execution_context.hpp>
|
||||
#include <boost/asio/executor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/socket_base.hpp>
|
||||
|
||||
@ -32,6 +32,8 @@
|
||||
# include <boost/asio/detail/null_socket_service.hpp>
|
||||
#elif defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/win_iocp_socket_service.hpp>
|
||||
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
# include <boost/asio/detail/io_uring_socket_service.hpp>
|
||||
#else
|
||||
# include <boost/asio/detail/reactive_socket_service.hpp>
|
||||
#endif
|
||||
@ -49,7 +51,7 @@ namespace asio {
|
||||
#define BOOST_ASIO_BASIC_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
template <typename Protocol, typename Executor = any_io_executor>
|
||||
class basic_socket;
|
||||
|
||||
#endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL)
|
||||
@ -88,6 +90,9 @@ public:
|
||||
#elif defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef typename detail::win_iocp_socket_service<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
typedef typename detail::io_uring_socket_service<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
#else
|
||||
typedef typename detail::reactive_socket_service<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
@ -112,7 +117,7 @@ public:
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*/
|
||||
explicit basic_socket(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
: impl_(0, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@ -126,10 +131,10 @@ public:
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
>::type = 0)
|
||||
: impl_(0, 0, context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -145,7 +150,7 @@ public:
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
basic_socket(const executor_type& ex, const protocol_type& protocol)
|
||||
: impl_(ex)
|
||||
: impl_(0, ex)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), protocol, ec);
|
||||
@ -166,10 +171,11 @@ public:
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_socket(ExecutionContext& context, const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||
defaulted_constraint
|
||||
>::type = defaulted_constraint())
|
||||
: impl_(0, 0, context)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), protocol, ec);
|
||||
@ -192,7 +198,7 @@ public:
|
||||
* @throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
basic_socket(const executor_type& ex, const endpoint_type& endpoint)
|
||||
: impl_(ex)
|
||||
: impl_(0, ex)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
const protocol_type protocol = endpoint.protocol();
|
||||
@ -220,10 +226,10 @@ public:
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_socket(ExecutionContext& context, const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
>::type = 0)
|
||||
: impl_(0, 0, context)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
const protocol_type protocol = endpoint.protocol();
|
||||
@ -248,7 +254,7 @@ public:
|
||||
*/
|
||||
basic_socket(const executor_type& ex, const protocol_type& protocol,
|
||||
const native_handle_type& native_socket)
|
||||
: impl_(ex)
|
||||
: impl_(0, ex)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
@ -273,10 +279,10 @@ public:
|
||||
template <typename ExecutionContext>
|
||||
basic_socket(ExecutionContext& context, const protocol_type& protocol,
|
||||
const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
>::type = 0)
|
||||
: impl_(0, 0, context)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
@ -332,10 +338,10 @@ public:
|
||||
*/
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_socket(basic_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
>::type = 0)
|
||||
: impl_(std::move(other.impl_))
|
||||
{
|
||||
}
|
||||
@ -351,7 +357,7 @@ public:
|
||||
* constructed using the @c basic_socket(const executor_type&) constructor.
|
||||
*/
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_socket&
|
||||
@ -939,6 +945,16 @@ public:
|
||||
* boost::asio::ip::address::from_string("1.2.3.4"), 12345);
|
||||
* socket.async_connect(endpoint, connect_handler);
|
||||
* @endcode
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
|
||||
@ -1772,6 +1788,16 @@ public:
|
||||
* ...
|
||||
* socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
|
||||
* @endcode
|
||||
*
|
||||
* @par Per-Operation Cancellation
|
||||
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||
* cancellation for the following boost::asio::cancellation_type values:
|
||||
*
|
||||
* @li @c cancellation_type::terminal
|
||||
*
|
||||
* @li @c cancellation_type::partial
|
||||
*
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <
|
||||
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
|
||||
@ -1802,6 +1828,9 @@ protected:
|
||||
#elif defined(BOOST_ASIO_HAS_IOCP)
|
||||
detail::io_object_impl<
|
||||
detail::win_iocp_socket_service<Protocol>, Executor> impl_;
|
||||
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||
detail::io_object_impl<
|
||||
detail::io_uring_socket_service<Protocol>, Executor> impl_;
|
||||
#else
|
||||
detail::io_object_impl<
|
||||
detail::reactive_socket_service<Protocol>, Executor> impl_;
|
||||
@ -1847,7 +1876,7 @@ private:
|
||||
detail::non_const_lvalue<ConnectHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_connect(
|
||||
self_->impl_.get_implementation(), peer_endpoint,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1879,8 +1908,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), w, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), w,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -2,7 +2,7 @@
|
||||
// buffer.hpp
|
||||
// ~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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)
|
||||
@ -50,11 +50,13 @@
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_BOOST_WORKAROUND)
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
|
||||
|| BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
|
||||
# if !defined(__clang__)
|
||||
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
# define BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
|
||||
# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
# elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
|
||||
# define BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
|
||||
# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
||||
// || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
|
||||
# endif // BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
|
||||
#endif // defined(BOOST_ASIO_HAS_BOOST_WORKAROUND)
|
||||
|
||||
#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
|
||||
@ -385,9 +387,9 @@ private:
|
||||
/// Get an iterator to the first element in a buffer sequence.
|
||||
template <typename MutableBuffer>
|
||||
inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<const MutableBuffer*, const mutable_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return static_cast<const mutable_buffer*>(detail::addressof(b));
|
||||
}
|
||||
@ -395,9 +397,9 @@ inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
|
||||
/// Get an iterator to the first element in a buffer sequence.
|
||||
template <typename ConstBuffer>
|
||||
inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<const ConstBuffer*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return static_cast<const const_buffer*>(detail::addressof(b));
|
||||
}
|
||||
@ -407,10 +409,10 @@ inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
|
||||
/// Get an iterator to the first element in a buffer sequence.
|
||||
template <typename C>
|
||||
inline auto buffer_sequence_begin(C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
@ -418,10 +420,10 @@ inline auto buffer_sequence_begin(C& c,
|
||||
/// Get an iterator to the first element in a buffer sequence.
|
||||
template <typename C>
|
||||
inline auto buffer_sequence_begin(const C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
@ -430,20 +432,20 @@ inline auto buffer_sequence_begin(const C& c,
|
||||
|
||||
template <typename C>
|
||||
inline typename C::iterator buffer_sequence_begin(C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
inline typename C::const_iterator buffer_sequence_begin(const C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
@ -462,9 +464,9 @@ inline typename C::const_iterator buffer_sequence_begin(const C& c,
|
||||
/// Get an iterator to one past the end element in a buffer sequence.
|
||||
template <typename MutableBuffer>
|
||||
inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<const MutableBuffer*, const mutable_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
|
||||
}
|
||||
@ -472,9 +474,9 @@ inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
|
||||
/// Get an iterator to one past the end element in a buffer sequence.
|
||||
template <typename ConstBuffer>
|
||||
inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
is_convertible<const ConstBuffer*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
|
||||
}
|
||||
@ -484,10 +486,10 @@ inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
|
||||
/// Get an iterator to one past the end element in a buffer sequence.
|
||||
template <typename C>
|
||||
inline auto buffer_sequence_end(C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
@ -495,10 +497,10 @@ inline auto buffer_sequence_end(C& c,
|
||||
/// Get an iterator to one past the end element in a buffer sequence.
|
||||
template <typename C>
|
||||
inline auto buffer_sequence_end(const C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
@ -507,20 +509,20 @@ inline auto buffer_sequence_end(const C& c,
|
||||
|
||||
template <typename C>
|
||||
inline typename C::iterator buffer_sequence_end(C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
inline typename C::const_iterator buffer_sequence_end(const C& c,
|
||||
typename enable_if<
|
||||
typename constraint<
|
||||
!is_convertible<const C*, const mutable_buffer*>::value
|
||||
&& !is_convertible<const C*, const const_buffer*>::value
|
||||
>::type* = 0) BOOST_ASIO_NOEXCEPT
|
||||
>::type = 0) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
307
boost/asio/cancellation_signal.hpp
Normal file
307
boost/asio/cancellation_signal.hpp
Normal file
@ -0,0 +1,307 @@
|
||||
//
|
||||
// cancellation_signal.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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_CANCELLATION_SIGNAL_HPP
|
||||
#define BOOST_ASIO_CANCELLATION_SIGNAL_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
#include <boost/asio/cancellation_type.hpp>
|
||||
#include <boost/asio/detail/cstddef.hpp>
|
||||
#include <boost/asio/detail/type_traits.hpp>
|
||||
#include <boost/asio/detail/variadic_templates.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class cancellation_handler_base
|
||||
{
|
||||
public:
|
||||
virtual void call(cancellation_type_t) = 0;
|
||||
virtual std::pair<void*, std::size_t> destroy() BOOST_ASIO_NOEXCEPT = 0;
|
||||
|
||||
protected:
|
||||
~cancellation_handler_base() {}
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
class cancellation_handler
|
||||
: public cancellation_handler_base
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
template <typename... Args>
|
||||
cancellation_handler(std::size_t size, BOOST_ASIO_MOVE_ARG(Args)... args)
|
||||
: handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
cancellation_handler(std::size_t size)
|
||||
: handler_(),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
#define BOOST_ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \
|
||||
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
|
||||
cancellation_handler(std::size_t size, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||
: handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)), \
|
||||
size_(size) \
|
||||
{ \
|
||||
} \
|
||||
/**/
|
||||
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_HANDLER_CTOR_DEF)
|
||||
#undef BOOST_ASIO_PRIVATE_HANDLER_CTOR_DEF
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
void call(cancellation_type_t type)
|
||||
{
|
||||
handler_(type);
|
||||
}
|
||||
|
||||
std::pair<void*, std::size_t> destroy() BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
std::pair<void*, std::size_t> mem(this, size_);
|
||||
this->cancellation_handler::~cancellation_handler();
|
||||
return mem;
|
||||
}
|
||||
|
||||
Handler& handler() BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return handler_;
|
||||
}
|
||||
|
||||
private:
|
||||
~cancellation_handler()
|
||||
{
|
||||
}
|
||||
|
||||
Handler handler_;
|
||||
std::size_t size_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class cancellation_slot;
|
||||
|
||||
/// A cancellation signal with a single slot.
|
||||
class cancellation_signal
|
||||
{
|
||||
public:
|
||||
BOOST_ASIO_CONSTEXPR cancellation_signal()
|
||||
: handler_(0)
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_ASIO_DECL ~cancellation_signal();
|
||||
|
||||
/// Emits the signal and causes invocation of the slot's handler, if any.
|
||||
void emit(cancellation_type_t type)
|
||||
{
|
||||
if (handler_)
|
||||
handler_->call(type);
|
||||
}
|
||||
|
||||
/// Returns the single slot associated with the signal.
|
||||
/**
|
||||
* The signal object must remain valid for as long the slot may be used.
|
||||
* Destruction of the signal invalidates the slot.
|
||||
*/
|
||||
cancellation_slot slot() BOOST_ASIO_NOEXCEPT;
|
||||
|
||||
private:
|
||||
cancellation_signal(const cancellation_signal&) BOOST_ASIO_DELETED;
|
||||
cancellation_signal& operator=(const cancellation_signal&) BOOST_ASIO_DELETED;
|
||||
|
||||
detail::cancellation_handler_base* handler_;
|
||||
};
|
||||
|
||||
/// A slot associated with a cancellation signal.
|
||||
class cancellation_slot
|
||||
{
|
||||
public:
|
||||
/// Creates a slot that is not connected to any cancellation signal.
|
||||
BOOST_ASIO_CONSTEXPR cancellation_slot()
|
||||
: handler_(0)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
/// Installs a handler into the slot, constructing the new object directly.
|
||||
/**
|
||||
* Destroys any existing handler in the slot, then installs the new handler,
|
||||
* constructing it with the supplied @c args.
|
||||
*
|
||||
* The handler is a function object to be called when the signal is emitted.
|
||||
* The signature of the handler must be
|
||||
* @code void handler(boost::asio::cancellation_type_t); @endcode
|
||||
*
|
||||
* @param args Arguments to be passed to the @c CancellationHandler object's
|
||||
* constructor.
|
||||
*
|
||||
* @returns A reference to the newly installed handler.
|
||||
*
|
||||
* @note Handlers installed into the slot via @c emplace are not required to
|
||||
* be copy constructible or move constructible.
|
||||
*/
|
||||
template <typename CancellationHandler, typename... Args>
|
||||
CancellationHandler& emplace(BOOST_ASIO_MOVE_ARG(Args)... args)
|
||||
{
|
||||
typedef detail::cancellation_handler<CancellationHandler>
|
||||
cancellation_handler_type;
|
||||
auto_delete_helper del = { prepare_memory(
|
||||
sizeof(cancellation_handler_type),
|
||||
BOOST_ASIO_ALIGNOF(CancellationHandler)) };
|
||||
cancellation_handler_type* handler_obj =
|
||||
new (del.mem.first) cancellation_handler_type(
|
||||
del.mem.second, BOOST_ASIO_MOVE_CAST(Args)(args)...);
|
||||
del.mem.first = 0;
|
||||
*handler_ = handler_obj;
|
||||
return handler_obj->handler();
|
||||
}
|
||||
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
template <typename CancellationHandler>
|
||||
CancellationHandler& emplace()
|
||||
{
|
||||
typedef detail::cancellation_handler<CancellationHandler>
|
||||
cancellation_handler_type;
|
||||
auto_delete_helper del = { prepare_memory(
|
||||
sizeof(cancellation_handler_type),
|
||||
BOOST_ASIO_ALIGNOF(CancellationHandler)) };
|
||||
cancellation_handler_type* handler_obj =
|
||||
new (del.mem.first) cancellation_handler_type(del.mem.second);
|
||||
del.mem.first = 0;
|
||||
*handler_ = handler_obj;
|
||||
return handler_obj->handler();
|
||||
}
|
||||
|
||||
#define BOOST_ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \
|
||||
template <typename CancellationHandler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
|
||||
CancellationHandler& emplace(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||
{ \
|
||||
typedef detail::cancellation_handler<CancellationHandler> \
|
||||
cancellation_handler_type; \
|
||||
auto_delete_helper del = { prepare_memory( \
|
||||
sizeof(cancellation_handler_type), \
|
||||
BOOST_ASIO_ALIGNOF(CancellationHandler)) }; \
|
||||
cancellation_handler_type* handler_obj = \
|
||||
new (del.mem.first) cancellation_handler_type( \
|
||||
del.mem.second, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||
del.mem.first = 0; \
|
||||
*handler_ = handler_obj; \
|
||||
return handler_obj->handler(); \
|
||||
} \
|
||||
/**/
|
||||
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_HANDLER_EMPLACE_DEF)
|
||||
#undef BOOST_ASIO_PRIVATE_HANDLER_EMPLACE_DEF
|
||||
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
|
||||
|
||||
/// Installs a handler into the slot.
|
||||
/**
|
||||
* Destroys any existing handler in the slot, then installs the new handler,
|
||||
* constructing it as a decay-copy of the supplied handler.
|
||||
*
|
||||
* The handler is a function object to be called when the signal is emitted.
|
||||
* The signature of the handler must be
|
||||
* @code void handler(boost::asio::cancellation_type_t); @endcode
|
||||
*
|
||||
* @param handler The handler to be installed.
|
||||
*
|
||||
* @returns A reference to the newly installed handler.
|
||||
*/
|
||||
template <typename CancellationHandler>
|
||||
typename decay<CancellationHandler>::type& assign(
|
||||
BOOST_ASIO_MOVE_ARG(CancellationHandler) handler)
|
||||
{
|
||||
return this->emplace<typename decay<CancellationHandler>::type>(
|
||||
BOOST_ASIO_MOVE_CAST(CancellationHandler)(handler));
|
||||
}
|
||||
|
||||
/// Clears the slot.
|
||||
/**
|
||||
* Destroys any existing handler in the slot.
|
||||
*/
|
||||
BOOST_ASIO_DECL void clear();
|
||||
|
||||
/// Returns whether the slot is connected to a signal.
|
||||
BOOST_ASIO_CONSTEXPR bool is_connected() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return handler_ != 0;
|
||||
}
|
||||
|
||||
/// Returns whether the slot is connected and has an installed handler.
|
||||
BOOST_ASIO_CONSTEXPR bool has_handler() const BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return handler_ != 0 && *handler_ != 0;
|
||||
}
|
||||
|
||||
/// Compare two slots for equality.
|
||||
friend BOOST_ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs,
|
||||
const cancellation_slot& rhs) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return lhs.handler_ == rhs.handler_;
|
||||
}
|
||||
|
||||
/// Compare two slots for inequality.
|
||||
friend BOOST_ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs,
|
||||
const cancellation_slot& rhs) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return lhs.handler_ != rhs.handler_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cancellation_signal;
|
||||
|
||||
BOOST_ASIO_CONSTEXPR cancellation_slot(int,
|
||||
detail::cancellation_handler_base** handler)
|
||||
: handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_ASIO_DECL std::pair<void*, std::size_t> prepare_memory(
|
||||
std::size_t size, std::size_t align);
|
||||
|
||||
struct auto_delete_helper
|
||||
{
|
||||
std::pair<void*, std::size_t> mem;
|
||||
|
||||
BOOST_ASIO_DECL ~auto_delete_helper();
|
||||
};
|
||||
|
||||
detail::cancellation_handler_base** handler_;
|
||||
};
|
||||
|
||||
inline cancellation_slot cancellation_signal::slot() BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return cancellation_slot(0, &handler_);
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HEADER_ONLY)
|
||||
# include <boost/asio/impl/cancellation_signal.ipp>
|
||||
#endif // defined(BOOST_ASIO_HEADER_ONLY)
|
||||
|
||||
#endif // BOOST_ASIO_CANCELLATION_SIGNAL_HPP
|
176
boost/asio/cancellation_type.hpp
Normal file
176
boost/asio/cancellation_type.hpp
Normal file
@ -0,0 +1,176 @@
|
||||
//
|
||||
// cancellation_type.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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_CANCELLATION_TYPE_HPP
|
||||
#define BOOST_ASIO_CANCELLATION_TYPE_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/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
# if defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Enumeration representing the different types of cancellation that may
|
||||
/// be requested from or implemented by an asynchronous operation.
|
||||
enum cancellation_type
|
||||
{
|
||||
/// Bitmask representing no types of cancellation.
|
||||
none = 0,
|
||||
|
||||
/// Requests cancellation where, following a successful cancellation, the only
|
||||
/// safe operations on the I/O object are closure or destruction.
|
||||
terminal = 1,
|
||||
|
||||
/// Requests cancellation where a successful cancellation may result in
|
||||
/// partial side effects or no side effects. Following cancellation, the I/O
|
||||
/// object is in a well-known state, and may be used for further operations.
|
||||
partial = 2,
|
||||
|
||||
/// Requests cancellation where a successful cancellation results in no
|
||||
/// apparent side effects. Following cancellation, the I/O object is in the
|
||||
/// same observable state as it was prior to the operation.
|
||||
total = 4,
|
||||
|
||||
/// Bitmask representing all types of cancellation.
|
||||
all = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
/// Portability typedef.
|
||||
typedef cancellation_type cancellation_type_t;
|
||||
|
||||
#elif defined(BOOST_ASIO_HAS_ENUM_CLASS)
|
||||
|
||||
enum class cancellation_type : unsigned int
|
||||
{
|
||||
none = 0,
|
||||
terminal = 1,
|
||||
partial = 2,
|
||||
total = 4,
|
||||
all = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
typedef cancellation_type cancellation_type_t;
|
||||
|
||||
#else // defined(BOOST_ASIO_HAS_ENUM_CLASS)
|
||||
|
||||
namespace cancellation_type {
|
||||
|
||||
enum cancellation_type_t
|
||||
{
|
||||
none = 0,
|
||||
terminal = 1,
|
||||
partial = 2,
|
||||
total = 4,
|
||||
all = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
} // namespace cancellation_type
|
||||
|
||||
typedef cancellation_type::cancellation_type_t cancellation_type_t;
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_ENUM_CLASS)
|
||||
|
||||
/// Negation operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline BOOST_ASIO_CONSTEXPR bool operator!(cancellation_type_t x)
|
||||
{
|
||||
return static_cast<unsigned int>(x) == 0;
|
||||
}
|
||||
|
||||
/// Bitwise and operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline BOOST_ASIO_CONSTEXPR cancellation_type_t operator&(
|
||||
cancellation_type_t x, cancellation_type_t y)
|
||||
{
|
||||
return static_cast<cancellation_type_t>(
|
||||
static_cast<unsigned int>(x) & static_cast<unsigned int>(y));
|
||||
}
|
||||
|
||||
/// Bitwise or operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline BOOST_ASIO_CONSTEXPR cancellation_type_t operator|(
|
||||
cancellation_type_t x, cancellation_type_t y)
|
||||
{
|
||||
return static_cast<cancellation_type_t>(
|
||||
static_cast<unsigned int>(x) | static_cast<unsigned int>(y));
|
||||
}
|
||||
|
||||
/// Bitwise xor operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline BOOST_ASIO_CONSTEXPR cancellation_type_t operator^(
|
||||
cancellation_type_t x, cancellation_type_t y)
|
||||
{
|
||||
return static_cast<cancellation_type_t>(
|
||||
static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));
|
||||
}
|
||||
|
||||
/// Bitwise negation operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline BOOST_ASIO_CONSTEXPR cancellation_type_t operator~(cancellation_type_t x)
|
||||
{
|
||||
return static_cast<cancellation_type_t>(~static_cast<unsigned int>(x));
|
||||
}
|
||||
|
||||
/// Bitwise and-assignment operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline cancellation_type_t& operator&=(
|
||||
cancellation_type_t& x, cancellation_type_t y)
|
||||
{
|
||||
x = x & y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Bitwise or-assignment operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline cancellation_type_t& operator|=(
|
||||
cancellation_type_t& x, cancellation_type_t y)
|
||||
{
|
||||
x = x | y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Bitwise xor-assignment operator.
|
||||
/**
|
||||
* @relates cancellation_type
|
||||
*/
|
||||
inline cancellation_type_t& operator^=(
|
||||
cancellation_type_t& x, cancellation_type_t y)
|
||||
{
|
||||
x = x ^ y;
|
||||
return x;
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_CANCELLATION_TYPE_HPP
|
@ -2,7 +2,7 @@
|
||||
// detail/array.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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-2021 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-2021 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
// detail/bind_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,137 @@ 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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
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,
|
||||
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// detail/buffer_sequence_adapter.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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/call_stack.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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-2021 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-2021 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
|
||||
|
@ -2,7 +2,7 @@
|
||||
// detail/concurrency_hint.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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-2021 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/cstddef.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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/dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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,10 +87,7 @@ 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(reactor_op* op, bool is_continuation);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
@ -101,6 +100,13 @@ public:
|
||||
// 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 +145,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-2021 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,10 +117,7 @@ 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);
|
||||
|
||||
// Start a new operation. The reactor operation will be performed when the
|
||||
// given descriptor is flagged as ready, or an error has occurred.
|
||||
@ -132,6 +131,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 +177,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-2021 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-2021 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.
|
||||
|
@ -2,7 +2,7 @@
|
||||
// detail/executor_function.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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/fd_set_adapter.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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-2021 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/gcc_arm_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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-2021 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-2021 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/global.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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 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 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);
|
||||
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;
|
||||
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-2021 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-2021 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-2021 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-2021 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-2021 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,92 +18,504 @@
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <boost/asio/detail/type_traits.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_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();
|
||||
execution::execute(
|
||||
boost::asio::prefer(executor_,
|
||||
execution::blocking.possibly,
|
||||
execution::allocator((get_associated_allocator)(handler))),
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
}
|
||||
|
||||
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&)
|
||||
{
|
||||
execution::execute(
|
||||
boost::asio::prefer(executor_, execution::blocking.possibly),
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
}
|
||||
|
||||
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_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&)
|
||||
{
|
||||
execution::execute(
|
||||
boost::asio::prefer(executor_, execution::blocking.possibly),
|
||||
BOOST_ASIO_MOVE_CAST(Function)(function));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
handler_work(const handler_work&);
|
||||
handler_work& operator=(const handler_work&);
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // 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-2021 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-2021 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/dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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(
|
||||
reactor_op* op, bool is_continuation)
|
||||
{
|
||||
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-2021 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>
|
||||
|
||||
@ -202,6 +203,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-2021 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)
|
||||
{
|
||||
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-2021 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>
|
||||
|
||||
@ -343,6 +344,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-2021 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-2021 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",
|
||||
|
114
boost/asio/detail/impl/io_uring_service.hpp
Normal file
114
boost/asio/detail/impl/io_uring_service.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
//
|
||||
// detail/impl/io_uring_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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
|
881
boost/asio/detail/impl/io_uring_service.ipp
Normal file
881
boost/asio/detail/impl/io_uring_service.ipp
Normal file
@ -0,0 +1,881 @@
|
||||
//
|
||||
// detail/impl/io_uring_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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/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;
|
||||
do_cancel_ops(io_obj, ops);
|
||||
io_obj->shutdown_ = true;
|
||||
io_object_lock.unlock();
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
|
||||
// Leave io_obj set so that it will be freed by the subsequent
|
||||
// call to cleanup_io_obj.
|
||||
}
|
||||
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 (result == 0 && usec > 0)
|
||||
{
|
||||
if (::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);
|
||||
submit_sqes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check_timers = false;
|
||||
int count = 0;
|
||||
while (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);
|
||||
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_EPOLL)
|
||||
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_EPOLL)
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_EPOLL)
|
||||
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_EPOLL)
|
||||
|
||||
void io_uring_service::register_with_reactor()
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_EPOLL)
|
||||
reactor_.register_internal_descriptor(reactor::read_op,
|
||||
event_fd_, reactor_data_, new event_fd_read_op(this));
|
||||
#endif // defined(BOOST_ASIO_HAS_EPOLL)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void 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();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
++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), first_op_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~perform_io_cleanup_on_block_exit()
|
||||
{
|
||||
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_;
|
||||
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 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
|
251
boost/asio/detail/impl/io_uring_socket_service_base.ipp
Normal file
251
boost/asio/detail/impl/io_uring_socket_service_base.ipp
Normal file
@ -0,0 +1,251 @@
|
||||
//
|
||||
// detail/io_uring_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2021 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-2021 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)
|
||||
{
|
||||
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-2021 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)))
|
||||
@ -283,6 +287,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-2021 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-2021 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-2021 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-2021 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_thread.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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/reactive_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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>
|
||||
|
||||
@ -298,5 +299,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-2021 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-2021 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);
|
||||
}
|
||||
@ -321,6 +331,17 @@ void scheduler::compensating_work_started()
|
||||
++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 +365,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 +490,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 +571,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 +626,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 +658,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-2021 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(
|
||||
reactor_op* op, bool is_continuation)
|
||||
{
|
||||
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-2021 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 {
|
||||
@ -81,13 +87,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;
|
||||
@ -165,6 +172,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 +260,11 @@ 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();
|
||||
interrupter_.recreate();
|
||||
}
|
||||
--retval;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// detail/impl/service_registry.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2021 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-2021 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
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user