update boost to 1.78.

This commit is contained in:
Zangetsu38 2021-12-11 14:07:32 +01:00 committed by Francisco José García García
parent a021ff3878
commit 0009f49022
4518 changed files with 305065 additions and 89672 deletions

24
Jamroot
View File

@ -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 ;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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 );

View File

@ -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
{

View File

@ -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 {

View File

@ -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() );
}

View File

@ -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&)
{

View File

@ -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() );
}

View File

@ -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

View File

@ -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>

View File

@ -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(

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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;
}
}

View 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

View 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

View File

@ -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

View 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
View 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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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>

View 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

View File

@ -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

View 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

View File

@ -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
View 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

View File

@ -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:

View File

@ -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:

View File

@ -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();
}

View 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

View 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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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);
}
};

View File

@ -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_;

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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)
{

View File

@ -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,

View File

@ -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)
{

View File

@ -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;
}
}
}

View File

@ -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",

View 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

View 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

View 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

View File

@ -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,

View File

@ -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)
{

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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))

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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();
}
}

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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)

View File

@ -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