update boost & add container lib (#204)

* remove boost headers

* boost 1.78
This commit is contained in:
Yun Hsiao Wu 2021-12-16 11:57:40 +08:00 committed by GitHub
parent 27fba2b278
commit 1aac2fcd8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4062 changed files with 387646 additions and 121292 deletions

View File

@ -13,7 +13,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/sources/CMakeLists.txt)
if(WINDOWS) if(WINDOWS)
if(${CMAKE_SIZEOF_VOID_P} STREQUAL "4") if(${CMAKE_SIZEOF_VOID_P} STREQUAL "4")
include(${CMAKE_CURRENT_LIST_DIR}/win32/CMakeLists.txt) include(${CMAKE_CURRENT_LIST_DIR}/win32/CMakeLists.txt)
else() else()
include(${CMAKE_CURRENT_LIST_DIR}/win64/CMakeLists.txt) include(${CMAKE_CURRENT_LIST_DIR}/win64/CMakeLists.txt)
endif() endif()

View File

@ -24,7 +24,6 @@ set(CC_UTILS_SOURCES
${CMAKE_CURRENT_LIST_DIR}/xxtea/xxtea.h ${CMAKE_CURRENT_LIST_DIR}/xxtea/xxtea.h
) )
set(CC_EXTERNAL_SOURCES set(CC_EXTERNAL_SOURCES
${CMAKE_CURRENT_LIST_DIR}/tommyds/tommy.c ${CMAKE_CURRENT_LIST_DIR}/tommyds/tommy.c
@ -32,13 +31,16 @@ set(CC_EXTERNAL_SOURCES
) )
if(NOT USE_MODULES) if(NOT USE_MODULES)
list(APPEND CC_EXTERNAL_SOURCES list(APPEND CC_EXTERNAL_SOURCES
${CC_UNZIP_SOURCES} ${CC_UNZIP_SOURCES}
${CC_TINYDIR_SOURCES} ${CC_TINYDIR_SOURCES}
${CC_UTILS_SOURCES} ${CC_UTILS_SOURCES}
) )
endif() endif()
# add dependent boost libs
include(${CMAKE_CURRENT_LIST_DIR}/boost-source/boost.cmake)
if(ANDROID OR OHOS) if(ANDROID OR OHOS)
include(${CMAKE_CURRENT_LIST_DIR}/pvmp3dec/CMakeLists.txt) include(${CMAKE_CURRENT_LIST_DIR}/pvmp3dec/CMakeLists.txt)
@ -70,4 +72,3 @@ if(USE_PHYSICS_PHYSX)
${CMAKE_CURRENT_LIST_DIR}/PhysX/PxShared/include ${CMAKE_CURRENT_LIST_DIR}/PhysX/PxShared/include
) )
endif() endif()

View File

@ -0,0 +1,14 @@
list(APPEND CC_EXTERNAL_PRIVATE_DEFINITIONS BOOST_ALL_NO_LIB)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/container boost/container)
set(BOOST_LIBS
boost_container
)
foreach(lib ${BOOST_LIBS})
set_target_properties(${lib} PROPERTIES FOLDER Utils)
endforeach()
list(APPEND CC_EXTERNAL_LIBS ${BOOST_LIBS})

View File

@ -0,0 +1,37 @@
# Copyright 2020, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5...3.16)
project(boost_container VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES C CXX)
add_library(boost_container
alloc_lib.c
dlmalloc.cpp
global_resource.cpp
monotonic_buffer_resource.cpp
pool_resource.cpp
synchronized_pool_resource.cpp
unsynchronized_pool_resource.cpp
)
add_library(Boost::container ALIAS boost_container)
target_compile_definitions(boost_container
PUBLIC BOOST_CONTAINER_NO_LIB
# Source files already define BOOST_CONTAINER_SOURCE
# PRIVATE BOOST_CONTAINER_SOURCE
)
if(BUILD_SHARED_LIBS)
target_compile_definitions(boost_container PUBLIC BOOST_CONTAINER_DYN_LINK)
else()
target_compile_definitions(boost_container PUBLIC BOOST_CONTAINER_STATIC_LINK)
endif()
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()

View File

@ -0,0 +1,27 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define DLMALLOC_VERSION 286
#ifndef DLMALLOC_VERSION
#error "DLMALLOC_VERSION undefined"
#endif
#ifdef __VXWORKS__
// no sbrk() in VxWorks, configure dlmalloc to use only mmap()
#define HAVE_MORECORE 0
#endif
#if DLMALLOC_VERSION == 286
#include "dlmalloc_ext_2_8_6.c"
#else
#error "Unsupported boost_cont_VERSION version"
#endif

View File

@ -0,0 +1,108 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/detail/dlmalloc.hpp>
namespace boost{
namespace container{
BOOST_CONTAINER_DECL size_t dlmalloc_size(const void *p)
{ return boost_cont_size(p); }
BOOST_CONTAINER_DECL void* dlmalloc_malloc(size_t bytes)
{ return boost_cont_malloc(bytes); }
BOOST_CONTAINER_DECL void dlmalloc_free(void* mem)
{ return boost_cont_free(mem); }
BOOST_CONTAINER_DECL void* dlmalloc_memalign(size_t bytes, size_t alignment)
{ return boost_cont_memalign(bytes, alignment); }
BOOST_CONTAINER_DECL int dlmalloc_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain)
{ return boost_cont_multialloc_nodes(n_elements, elem_size, contiguous_elements, pchain); }
BOOST_CONTAINER_DECL int dlmalloc_multialloc_arrays
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain)
{ return boost_cont_multialloc_arrays(n_elements, sizes, sizeof_element, contiguous_elements, pchain); }
BOOST_CONTAINER_DECL void dlmalloc_multidealloc(boost_cont_memchain *pchain)
{ return boost_cont_multidealloc(pchain); }
BOOST_CONTAINER_DECL size_t dlmalloc_footprint()
{ return boost_cont_footprint(); }
BOOST_CONTAINER_DECL size_t dlmalloc_allocated_memory()
{ return boost_cont_allocated_memory(); }
BOOST_CONTAINER_DECL size_t dlmalloc_chunksize(const void *p)
{ return boost_cont_chunksize(p); }
BOOST_CONTAINER_DECL int dlmalloc_all_deallocated()
{ return boost_cont_all_deallocated(); }
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t dlmalloc_malloc_stats()
{ return boost_cont_malloc_stats(); }
BOOST_CONTAINER_DECL size_t dlmalloc_in_use_memory()
{ return boost_cont_in_use_memory(); }
BOOST_CONTAINER_DECL int dlmalloc_trim(size_t pad)
{ return boost_cont_trim(pad); }
BOOST_CONTAINER_DECL int dlmalloc_mallopt(int parameter_number, int parameter_value)
{ return boost_cont_mallopt(parameter_number, parameter_value); }
BOOST_CONTAINER_DECL int dlmalloc_grow
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received)
{ return boost_cont_grow(oldmem, minbytes, maxbytes, received); }
BOOST_CONTAINER_DECL int dlmalloc_shrink
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit)
{ return boost_cont_shrink(oldmem, minbytes, maxbytes, received, do_commit); }
BOOST_CONTAINER_DECL void* dlmalloc_alloc
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes)
{ return boost_cont_alloc(minbytes, preferred_bytes, received_bytes); }
BOOST_CONTAINER_DECL int dlmalloc_malloc_check()
{ return boost_cont_malloc_check(); }
BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
( allocation_type command
, size_t sizeof_object
, size_t limit_objects
, size_t preferred_objects
, size_t *received_objects
, void *reuse_ptr
)
{ return boost_cont_allocation_command(command, sizeof_object, limit_objects, preferred_objects, received_objects, reuse_ptr); }
BOOST_CONTAINER_DECL void *dlmalloc_sync_create()
{ return boost_cont_sync_create(); }
BOOST_CONTAINER_DECL void dlmalloc_sync_destroy(void *sync)
{ return boost_cont_sync_destroy(sync); }
BOOST_CONTAINER_DECL bool dlmalloc_sync_lock(void *sync)
{ return boost_cont_sync_lock(sync) != 0; }
BOOST_CONTAINER_DECL void dlmalloc_sync_unlock(void *sync)
{ return boost_cont_sync_unlock(sync); }
BOOST_CONTAINER_DECL bool dlmalloc_global_sync_lock()
{ return boost_cont_global_sync_lock() != 0; }
BOOST_CONTAINER_DECL void dlmalloc_global_sync_unlock()
{ return boost_cont_global_sync_unlock(); }
} //namespace container{
} //namespace boost{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/dlmalloc.hpp> //For global lock
#include <boost/container/detail/singleton.hpp>
#include <cstddef>
#include <new>
namespace boost {
namespace container {
namespace pmr {
class new_delete_resource_imp
: public memory_resource
{
public:
~new_delete_resource_imp() BOOST_OVERRIDE
{}
void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
{ (void)bytes; (void)alignment; return new char[bytes]; }
void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
{ (void)bytes; (void)alignment; delete[]((char*)p); }
bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE
{ return &other == this; }
};
struct null_memory_resource_imp
: public memory_resource
{
public:
~null_memory_resource_imp() BOOST_OVERRIDE
{}
void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
{
(void)bytes; (void)alignment;
#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) || defined(BOOST_NO_EXCEPTIONS)
throw_bad_alloc();
#else
throw std::bad_alloc();
#endif
return 0;
}
void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
{ (void)p; (void)bytes; (void)alignment; }
bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE
{ return &other == this; }
};
BOOST_CONTAINER_DECL memory_resource* new_delete_resource() BOOST_NOEXCEPT
{
return &boost::container::dtl::singleton_default<new_delete_resource_imp>::instance();
}
BOOST_CONTAINER_DECL memory_resource* null_memory_resource() BOOST_NOEXCEPT
{
return &boost::container::dtl::singleton_default<null_memory_resource_imp>::instance();
}
static memory_resource *default_memory_resource =
&boost::container::dtl::singleton_default<new_delete_resource_imp>::instance();
BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT
{
//TO-DO: synchronizes-with part using atomics
if(dlmalloc_global_sync_lock()){
memory_resource *previous = default_memory_resource;
if(!previous){
//function called before main, default_memory_resource is not initialized yet
previous = new_delete_resource();
}
default_memory_resource = r ? r : new_delete_resource();
dlmalloc_global_sync_unlock();
return previous;
}
else{
return new_delete_resource();
}
}
BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT
{
//TO-DO: synchronizes-with part using atomics
if(dlmalloc_global_sync_lock()){
memory_resource *current = default_memory_resource;
if(!current){
//function called before main, default_memory_resource is not initialized yet
current = new_delete_resource();
}
dlmalloc_global_sync_unlock();
return current;
}
else{
return new_delete_resource();
}
}
} //namespace pmr {
} //namespace container {
} //namespace boost {

View File

@ -0,0 +1,175 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <boost/container/detail/min_max.hpp>
#include <boost/intrusive/detail/math.hpp>
#include <boost/container/throw_exception.hpp>
#include <new>
#include <cstddef>
namespace {
#ifdef BOOST_HAS_INTPTR_T
typedef boost::uintptr_t uintptr_type;
#else
typedef std::size_t uintptr_type;
#endif
static const std::size_t minimum_buffer_size = 2*sizeof(void*);
} //namespace {
namespace boost {
namespace container {
namespace pmr {
void monotonic_buffer_resource::increase_next_buffer()
{
m_next_buffer_size = (std::size_t(-1)/2 < m_next_buffer_size) ? std::size_t(-1) : m_next_buffer_size*2;
}
void monotonic_buffer_resource::increase_next_buffer_at_least_to(std::size_t minimum_size)
{
if(m_next_buffer_size < minimum_size){
if(bi::detail::is_pow2(minimum_size)){
m_next_buffer_size = minimum_size;
}
else if(std::size_t(-1)/2 < minimum_size){
m_next_buffer_size = minimum_size;
}
else{
m_next_buffer_size = bi::detail::ceil_pow2(minimum_size);
}
}
}
monotonic_buffer_resource::monotonic_buffer_resource(memory_resource* upstream) BOOST_NOEXCEPT
: m_memory_blocks(upstream ? *upstream : *get_default_resource())
, m_current_buffer(0)
, m_current_buffer_size(0u)
, m_next_buffer_size(initial_next_buffer_size)
, m_initial_buffer(0)
, m_initial_buffer_size(0u)
{}
monotonic_buffer_resource::monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream) BOOST_NOEXCEPT
: m_memory_blocks(upstream ? *upstream : *get_default_resource())
, m_current_buffer(0)
, m_current_buffer_size(0u)
, m_next_buffer_size(minimum_buffer_size)
, m_initial_buffer(0)
, m_initial_buffer_size(0u)
{ //In case initial_size is zero
this->increase_next_buffer_at_least_to(initial_size + !initial_size);
}
monotonic_buffer_resource::monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream) BOOST_NOEXCEPT
: m_memory_blocks(upstream ? *upstream : *get_default_resource())
, m_current_buffer(buffer)
, m_current_buffer_size(buffer_size)
, m_next_buffer_size
(bi::detail::previous_or_equal_pow2
(boost::container::dtl::max_value(buffer_size, std::size_t(initial_next_buffer_size))))
, m_initial_buffer(buffer)
, m_initial_buffer_size(buffer_size)
{ this->increase_next_buffer(); }
monotonic_buffer_resource::~monotonic_buffer_resource()
{ this->release(); }
void monotonic_buffer_resource::release() BOOST_NOEXCEPT
{
m_memory_blocks.release();
m_current_buffer = m_initial_buffer;
m_current_buffer_size = m_initial_buffer_size;
m_next_buffer_size = initial_next_buffer_size;
}
memory_resource* monotonic_buffer_resource::upstream_resource() const BOOST_NOEXCEPT
{ return &m_memory_blocks.upstream_resource(); }
std::size_t monotonic_buffer_resource::remaining_storage(std::size_t alignment, std::size_t &wasted_due_to_alignment) const BOOST_NOEXCEPT
{
const uintptr_type up_alignment_minus1 = alignment - 1u;
const uintptr_type up_alignment_mask = ~up_alignment_minus1;
const uintptr_type up_addr = uintptr_type(m_current_buffer);
const uintptr_type up_aligned_addr = (up_addr + up_alignment_minus1) & up_alignment_mask;
wasted_due_to_alignment = std::size_t(up_aligned_addr - up_addr);
return m_current_buffer_size <= wasted_due_to_alignment ? 0u : m_current_buffer_size - wasted_due_to_alignment;
}
std::size_t monotonic_buffer_resource::remaining_storage(std::size_t alignment) const BOOST_NOEXCEPT
{
std::size_t ignore_this;
return this->remaining_storage(alignment, ignore_this);
}
const void *monotonic_buffer_resource::current_buffer() const BOOST_NOEXCEPT
{ return m_current_buffer; }
std::size_t monotonic_buffer_resource::next_buffer_size() const BOOST_NOEXCEPT
{ return m_next_buffer_size; }
void *monotonic_buffer_resource::allocate_from_current(std::size_t aligner, std::size_t bytes)
{
char * p = (char*)m_current_buffer + aligner;
m_current_buffer = p + bytes;
m_current_buffer_size -= aligner + bytes;
return p;
}
void* monotonic_buffer_resource::do_allocate(std::size_t bytes, std::size_t alignment)
{
if(alignment > memory_resource::max_align){
(void)bytes; (void)alignment;
#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) || defined(BOOST_NO_EXCEPTIONS)
throw_bad_alloc();
#else
throw std::bad_alloc();
#endif
}
//See if there is room in current buffer
std::size_t aligner = 0u;
if(this->remaining_storage(alignment, aligner) < bytes){
//The new buffer will be aligned to the strictest alignment so reset
//the aligner, which was needed for the old buffer.
aligner = 0u;
//Update next_buffer_size to at least bytes
this->increase_next_buffer_at_least_to(bytes);
//Now allocate and update internal data
m_current_buffer = (char*)m_memory_blocks.allocate(m_next_buffer_size);
m_current_buffer_size = m_next_buffer_size;
this->increase_next_buffer();
}
//Enough internal storage, extract from it
return this->allocate_from_current(aligner, bytes);
}
void monotonic_buffer_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_NOEXCEPT
{ (void)p; (void)bytes; (void)alignment; }
bool monotonic_buffer_resource::do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
{ return this == &other; }
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>

View File

@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <boost/container/detail/pool_resource.hpp>
#include <boost/container/detail/block_slist.hpp>
#include <boost/container/detail/min_max.hpp>
#include <boost/container/detail/placement_new.hpp>
#include <boost/intrusive/linear_slist_algorithms.hpp>
#include <boost/intrusive/detail/math.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//pool_data_t
class pool_data_t
: public block_slist_base<>
{
typedef block_slist_base<> block_slist_base_t;
public:
explicit pool_data_t(std::size_t initial_blocks_per_chunk)
: block_slist_base_t(), next_blocks_per_chunk(initial_blocks_per_chunk)
{ slist_algo::init_header(&free_slist); }
void *allocate_block() BOOST_NOEXCEPT
{
if(slist_algo::unique(&free_slist)){
return 0;
}
slist_node *pv = slist_algo::node_traits::get_next(&free_slist);
slist_algo::unlink_after(&free_slist);
pv->~slist_node();
return pv;
}
void deallocate_block(void *p) BOOST_NOEXCEPT
{
slist_node *pv = ::new(p, boost_container_new_t()) slist_node();
slist_algo::link_after(&free_slist, pv);
}
void release(memory_resource &upstream)
{
slist_algo::init_header(&free_slist);
this->block_slist_base_t::release(upstream);
next_blocks_per_chunk = pool_options_minimum_max_blocks_per_chunk;
}
void replenish(memory_resource &mr, std::size_t pool_block, std::size_t max_blocks_per_chunk)
{
//Limit max value
std::size_t blocks_per_chunk = boost::container::dtl::min_value(max_blocks_per_chunk, next_blocks_per_chunk);
//Avoid overflow
blocks_per_chunk = boost::container::dtl::min_value(blocks_per_chunk, std::size_t(-1)/pool_block);
//Minimum block size is at least max_align, so all pools allocate sizes that are multiple of max_align,
//meaning that all blocks are max_align-aligned.
char *p = static_cast<char *>(block_slist_base_t::allocate(blocks_per_chunk*pool_block, mr));
//Create header types. This is no-throw
for(std::size_t i = 0, max = blocks_per_chunk; i != max; ++i){
slist_node *const pv = ::new(p, boost_container_new_t()) slist_node();
slist_algo::link_after(&free_slist, pv);
p += pool_block;
}
//Update next block per chunk
next_blocks_per_chunk = max_blocks_per_chunk/2u < blocks_per_chunk ? max_blocks_per_chunk : blocks_per_chunk*2u;
}
std::size_t cache_count() const
{ return slist_algo::count(&free_slist) - 1u; }
slist_node free_slist;
std::size_t next_blocks_per_chunk;
};
//pool_resource
//Detect overflow in ceil_pow2
BOOST_STATIC_ASSERT(pool_options_default_max_blocks_per_chunk <= (std::size_t(-1)/2u+1u));
//Sanity checks
BOOST_STATIC_ASSERT(bi::detail::static_is_pow2<pool_options_default_max_blocks_per_chunk>::value);
BOOST_STATIC_ASSERT(bi::detail::static_is_pow2<pool_options_minimum_largest_required_pool_block>::value);
//unsynchronized_pool_resource
void pool_resource::priv_limit_option(std::size_t &val, std::size_t min, std::size_t max) //static
{
if(!val){
val = max;
}
else{
val = val < min ? min : boost::container::dtl::min_value(val, max);
}
}
std::size_t pool_resource::priv_pool_index(std::size_t block_size) //static
{
//For allocations equal or less than pool_options_minimum_largest_required_pool_block
//the smallest pool is used
block_size = boost::container::dtl::max_value(block_size, pool_options_minimum_largest_required_pool_block);
return bi::detail::ceil_log2(block_size)
- bi::detail::ceil_log2(pool_options_minimum_largest_required_pool_block);
}
std::size_t pool_resource::priv_pool_block(std::size_t index) //static
{
//For allocations equal or less than pool_options_minimum_largest_required_pool_block
//the smallest pool is used
return pool_options_minimum_largest_required_pool_block << index;
}
void pool_resource::priv_fix_options()
{
priv_limit_option(m_options.max_blocks_per_chunk
, pool_options_minimum_max_blocks_per_chunk
, pool_options_default_max_blocks_per_chunk);
priv_limit_option
( m_options.largest_required_pool_block
, pool_options_minimum_largest_required_pool_block
, pool_options_default_largest_required_pool_block);
m_options.largest_required_pool_block = bi::detail::ceil_pow2(m_options.largest_required_pool_block);
}
void pool_resource::priv_init_pools()
{
const std::size_t num_pools = priv_pool_index(m_options.largest_required_pool_block)+1u;
//Otherwise, just use the default alloc (zero pools)
void *p = 0;
//This can throw
p = m_upstream.allocate(sizeof(pool_data_t)*num_pools);
//This is nothrow
m_pool_data = static_cast<pool_data_t *>(p);
for(std::size_t i = 0, max = num_pools; i != max; ++i){
::new(&m_pool_data[i], boost_container_new_t()) pool_data_t(pool_options_minimum_max_blocks_per_chunk);
}
m_pool_count = num_pools;
}
void pool_resource::priv_constructor_body()
{
this->priv_fix_options();
}
pool_resource::pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT
: m_options(opts), m_upstream(*upstream), m_oversized_list(), m_pool_data(), m_pool_count()
{ this->priv_constructor_body(); }
pool_resource::pool_resource() BOOST_NOEXCEPT
: m_options(), m_upstream(*get_default_resource()), m_oversized_list(), m_pool_data(), m_pool_count()
{ this->priv_constructor_body(); }
pool_resource::pool_resource(memory_resource* upstream) BOOST_NOEXCEPT
: m_options(), m_upstream(*upstream), m_oversized_list(), m_pool_data(), m_pool_count()
{ this->priv_constructor_body(); }
pool_resource::pool_resource(const pool_options& opts) BOOST_NOEXCEPT
: m_options(opts), m_upstream(*get_default_resource()), m_oversized_list(), m_pool_data(), m_pool_count()
{ this->priv_constructor_body(); }
pool_resource::~pool_resource()
{
this->release();
for(std::size_t i = 0, max = m_pool_count; i != max; ++i){
m_pool_data[i].~pool_data_t();
}
if(m_pool_data){
m_upstream.deallocate((void*)m_pool_data, sizeof(pool_data_t)*m_pool_count);
}
}
void pool_resource::release()
{
m_oversized_list.release(m_upstream);
for(std::size_t i = 0, max = m_pool_count; i != max; ++i)
{
m_pool_data[i].release(m_upstream);
}
}
memory_resource* pool_resource::upstream_resource() const
{ return &m_upstream; }
pool_options pool_resource::options() const
{ return m_options; }
void* pool_resource::do_allocate(std::size_t bytes, std::size_t alignment)
{
if(!m_pool_data){
this->priv_init_pools();
}
(void)alignment; //alignment ignored here, max_align is used by pools
if(bytes > m_options.largest_required_pool_block){
return m_oversized_list.allocate(bytes, m_upstream);
}
else{
const std::size_t pool_idx = priv_pool_index(bytes);
pool_data_t & pool = m_pool_data[pool_idx];
void *p = pool.allocate_block();
if(!p){
pool.replenish(m_upstream, priv_pool_block(pool_idx), m_options.max_blocks_per_chunk);
p = pool.allocate_block();
}
return p;
}
}
void pool_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
{
(void)alignment; //alignment ignored here, max_align is used by pools
if(bytes > m_options.largest_required_pool_block){
//Just cached
return m_oversized_list.deallocate(p, m_upstream);
}
else{
const std::size_t pool_idx = priv_pool_index(bytes);
return m_pool_data[pool_idx].deallocate_block(p);
}
}
std::size_t pool_resource::pool_count() const
{
if(BOOST_LIKELY((0 != m_pool_data))){
return m_pool_count;
}
else{
return priv_pool_index(m_options.largest_required_pool_block)+1u;
}
}
std::size_t pool_resource::pool_index(std::size_t bytes) const
{
if(bytes > m_options.largest_required_pool_block){
return pool_count();
}
else{
return priv_pool_index(bytes);
}
}
std::size_t pool_resource::pool_next_blocks_per_chunk(std::size_t pool_idx) const
{
if(BOOST_LIKELY((m_pool_data && pool_idx < m_pool_count))){
return m_pool_data[pool_idx].next_blocks_per_chunk;
}
else{
return 1u;
}
}
std::size_t pool_resource::pool_block(std::size_t pool_idx) const
{ return priv_pool_block(pool_idx); }
std::size_t pool_resource::pool_cached_blocks(std::size_t pool_idx) const
{
if(BOOST_LIKELY((m_pool_data && pool_idx < m_pool_count))){
return m_pool_data[pool_idx].cache_count();
}
else{
return 0u;
}
}
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>

View File

@ -0,0 +1,111 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/thread_mutex.hpp>
#include <boost/container/pmr/synchronized_pool_resource.hpp>
#include <cstddef>
namespace {
using namespace boost::container::dtl;
class thread_mutex_lock
{
thread_mutex &m_mut;
public:
explicit thread_mutex_lock(thread_mutex &m)
: m_mut(m)
{
m_mut.lock();
}
~thread_mutex_lock()
{
m_mut.unlock();
}
};
} //namespace {
namespace boost {
namespace container {
namespace pmr {
synchronized_pool_resource::synchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT
: m_mut(), m_pool_resource(opts, upstream)
{}
synchronized_pool_resource::synchronized_pool_resource() BOOST_NOEXCEPT
: m_mut(), m_pool_resource()
{}
synchronized_pool_resource::synchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT
: m_mut(), m_pool_resource(upstream)
{}
synchronized_pool_resource::synchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT
: m_mut(), m_pool_resource(opts)
{}
synchronized_pool_resource::~synchronized_pool_resource() //virtual
{}
void synchronized_pool_resource::release()
{
thread_mutex_lock lck(m_mut); (void)lck;
m_pool_resource.release();
}
memory_resource* synchronized_pool_resource::upstream_resource() const
{ return m_pool_resource.upstream_resource(); }
pool_options synchronized_pool_resource::options() const
{ return m_pool_resource.options(); }
void* synchronized_pool_resource::do_allocate(std::size_t bytes, std::size_t alignment) //virtual
{
thread_mutex_lock lck(m_mut); (void)lck;
return m_pool_resource.do_allocate(bytes, alignment);
}
void synchronized_pool_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment) //virtual
{
thread_mutex_lock lck(m_mut); (void)lck;
return m_pool_resource.do_deallocate(p, bytes, alignment);
}
bool synchronized_pool_resource::do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT //virtual
{ return this == &other; }
std::size_t synchronized_pool_resource::pool_count() const
{ return m_pool_resource.pool_count(); }
std::size_t synchronized_pool_resource::pool_index(std::size_t bytes) const
{ return m_pool_resource.pool_index(bytes); }
std::size_t synchronized_pool_resource::pool_next_blocks_per_chunk(std::size_t pool_idx) const
{ return m_pool_resource.pool_next_blocks_per_chunk(pool_idx); }
std::size_t synchronized_pool_resource::pool_block(std::size_t pool_idx) const
{ return m_pool_resource.pool_block(pool_idx); }
std::size_t synchronized_pool_resource::pool_cached_blocks(std::size_t pool_idx) const
{ return m_pool_resource.pool_cached_blocks(pool_idx); }
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>

View File

@ -0,0 +1,79 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_CONTAINER_SOURCE
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/pmr/unsynchronized_pool_resource.hpp>
namespace boost {
namespace container {
namespace pmr {
unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT
: m_resource(opts, upstream)
{}
unsynchronized_pool_resource::unsynchronized_pool_resource() BOOST_NOEXCEPT
: m_resource()
{}
unsynchronized_pool_resource::unsynchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT
: m_resource(upstream)
{}
unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT
: m_resource(opts)
{}
unsynchronized_pool_resource::~unsynchronized_pool_resource() //virtual
{}
void unsynchronized_pool_resource::release()
{
m_resource.release();
}
memory_resource* unsynchronized_pool_resource::upstream_resource() const
{ return m_resource.upstream_resource(); }
pool_options unsynchronized_pool_resource::options() const
{ return m_resource.options(); }
void* unsynchronized_pool_resource::do_allocate(std::size_t bytes, std::size_t alignment) //virtual
{ return m_resource.do_allocate(bytes, alignment); }
void unsynchronized_pool_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment) //virtual
{ return m_resource.do_deallocate(p, bytes, alignment); }
bool unsynchronized_pool_resource::do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT //virtual
{ return this == &other; }
std::size_t unsynchronized_pool_resource::pool_count() const
{ return m_resource.pool_count(); }
std::size_t unsynchronized_pool_resource::pool_index(std::size_t bytes) const
{ return m_resource.pool_index(bytes); }
std::size_t unsynchronized_pool_resource::pool_next_blocks_per_chunk(std::size_t pool_idx) const
{ return m_resource.pool_next_blocks_per_chunk(pool_idx); }
std::size_t unsynchronized_pool_resource::pool_block(std::size_t pool_idx) const
{ return m_resource.pool_block(pool_idx); }
std::size_t unsynchronized_pool_resource::pool_cached_blocks(std::size_t pool_idx) const
{ return m_resource.pool_cached_blocks(pool_idx); }
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>

View File

@ -8,9 +8,9 @@
#ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 #ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 #define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) #if defined(_MSC_VER) || defined(__BORLANDC__) && !defined(__clang__) || defined(__DMC__)
# pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp") # pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp")
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) #elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) || defined(__BORLANDC__)
# warning "This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp" # warning "This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp"
#endif #endif

View File

@ -8,9 +8,9 @@
#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) #if defined(_MSC_VER) || defined(__BORLANDC__) && !defined(__clang__) || defined(__DMC__)
# pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp") # pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp")
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) #elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__) || defined(__BORLANDC__)
# warning "This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp" # warning "This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp"
#endif #endif

View File

@ -19,7 +19,6 @@
#define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP #define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP
#include <algorithm> #include <algorithm>
#include <type_traits>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>

View File

@ -9,8 +9,8 @@
/// \brief Combine the (transformed) elements of a sequence (or two) into a single value. /// \brief Combine the (transformed) elements of a sequence (or two) into a single value.
/// \author Marshall Clow /// \author Marshall Clow
#ifndef BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP #ifndef BOOST_ALGORITHM_INCLUSIVE_SCAN_HPP
#define BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP #define BOOST_ALGORITHM_INCLUSIVE_SCAN_HPP
#include <functional> // for std::plus #include <functional> // for std::plus
#include <iterator> // for std::iterator_traits #include <iterator> // for std::iterator_traits
@ -58,4 +58,4 @@ OutputIterator inclusive_scan(InputIterator first, InputIterator last,
}} // namespace boost and algorithm }} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_TRANSFORM_REDUCE_HPP #endif // BOOST_ALGORITHM_INCLUSIVE_SCAN_HPP

View File

@ -15,6 +15,9 @@
#include <locale> #include <locale>
#include <functional> #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> #include <boost/type_traits/make_unsigned.hpp>
namespace boost { namespace boost {

View File

@ -13,10 +13,12 @@
#include <boost/algorithm/string/config.hpp> #include <boost/algorithm/string/config.hpp>
#include <algorithm> #include <algorithm>
#include <cstring>
#include <functional> #include <functional>
#include <locale> #include <locale>
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/distance.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
#include <boost/algorithm/string/predicate_facade.hpp> #include <boost/algorithm/string/predicate_facade.hpp>

View File

@ -18,6 +18,8 @@
#include <boost/algorithm/string/detail/find_format_store.hpp> #include <boost/algorithm/string/detail/find_format_store.hpp>
#include <boost/algorithm/string/detail/replace_storage.hpp> #include <boost/algorithm/string/detail/replace_storage.hpp>
#include <deque>
namespace boost { namespace boost {
namespace algorithm { namespace algorithm {
namespace detail { namespace detail {

View File

@ -10,7 +10,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/config.hpp> #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> #include <boost/align/detail/align_cxx11.hpp>
#else #else
#include <boost/align/detail/align.hpp> #include <boost/align/detail/align.hpp>

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2014-2016 Glen Joseph Fernandes Copyright 2014-2020 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@ -19,13 +19,15 @@ align(std::size_t alignment, std::size_t size, void*& ptr,
std::size_t& space) std::size_t& space)
{ {
BOOST_ASSERT(boost::alignment::detail::is_alignment(alignment)); BOOST_ASSERT(boost::alignment::detail::is_alignment(alignment));
char* p = reinterpret_cast<char*>(~(alignment - 1) & if (size <= space) {
(reinterpret_cast<std::size_t>(ptr) + alignment - 1)); char* p = reinterpret_cast<char*>(~(alignment - 1) &
std::size_t n = p - static_cast<char*>(ptr); (reinterpret_cast<std::size_t>(ptr) + alignment - 1));
if (size + n <= space) { std::size_t n = p - static_cast<char*>(ptr);
ptr = p; if (n <= space - size) {
space -= n; ptr = p;
return p; space -= n;
return p;
}
} }
return 0; return 0;
} }

View File

@ -3,18 +3,20 @@
#ifndef BOOST_ANY_INCLUDED #ifndef BOOST_ANY_INCLUDED
#define BOOST_ANY_INCLUDED #define BOOST_ANY_INCLUDED
#if defined(_MSC_VER) #include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once # pragma once
#endif #endif
// what: variant type boost::any // what: variant type boost::any
// who: contributed by Kevlin Henney, // who: contributed by Kevlin Henney,
// with features contributed and bugs found by // with features contributed and bugs found by
// Antony Polukhin, Ed Brey, Mark Rodgers, // Antony Polukhin, Ed Brey, Mark Rodgers,
// Peter Dimov, and James Curran // Peter Dimov, and James Curran
// when: July 2001, April 2013 - 2020 // when: July 2001, April 2013 - 2020
#include <boost/config.hpp> #include <boost/any/bad_any_cast.hpp>
#include <boost/any/fwd.hpp>
#include <boost/type_index.hpp> #include <boost/type_index.hpp>
#include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp> #include <boost/type_traits/decay.hpp>
@ -27,7 +29,6 @@
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/core/addressof.hpp> #include <boost/core/addressof.hpp>
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/conditional.hpp> #include <boost/type_traits/conditional.hpp>
namespace boost namespace boost
@ -47,6 +48,10 @@ namespace boost
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
>(value)) >(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) any(const any & other)
@ -69,6 +74,10 @@ namespace boost
, typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&` , 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))) : 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 #endif
@ -92,6 +101,10 @@ namespace boost
template<typename ValueType> template<typename ValueType>
any & operator=(const ValueType & rhs) 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); any(rhs).swap(*this);
return *this; return *this;
} }
@ -102,7 +115,7 @@ namespace boost
return *this; return *this;
} }
#else #else
any & operator=(const any& rhs) any & operator=(const any& rhs)
{ {
any(rhs).swap(*this); any(rhs).swap(*this);
@ -121,6 +134,10 @@ namespace boost
template <class ValueType> template <class ValueType>
any & operator=(ValueType&& rhs) 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); any(static_cast<ValueType&&>(rhs)).swap(*this);
return *this; return *this;
} }
@ -224,27 +241,12 @@ namespace boost
placeholder * content; placeholder * content;
}; };
inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT
{ {
lhs.swap(rhs); lhs.swap(rhs);
} }
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";
}
};
template<typename ValueType> template<typename ValueType>
ValueType * any_cast(any * operand) BOOST_NOEXCEPT ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{ {
@ -271,9 +273,9 @@ namespace boost
if(!result) if(!result)
boost::throw_exception(bad_any_cast()); 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: // `ValueType` is not a reference. Example:
// `static_cast<std::string>(*result);` // `static_cast<std::string>(*result);`
// which is equal to `std::string(*result);` // which is equal to `std::string(*result);`
typedef BOOST_DEDUCED_TYPENAME boost::conditional< typedef BOOST_DEDUCED_TYPENAME boost::conditional<
boost::is_reference<ValueType>::value, boost::is_reference<ValueType>::value,
@ -305,7 +307,7 @@ namespace boost
BOOST_STATIC_ASSERT_MSG( BOOST_STATIC_ASSERT_MSG(
boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ 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::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); return any_cast<ValueType>(operand);
} }
@ -333,7 +335,7 @@ namespace boost
} }
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
// Copyright Antony Polukhin, 2013-2020. // Copyright Antony Polukhin, 2013-2021.
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // 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

View File

@ -0,0 +1,480 @@
// Copyright Ruslan Arutyunyan, 2019-2021.
// 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_ANYS_BASIC_ANY_HPP_INCLUDED
#define BOOST_ANYS_BASIC_ANY_HPP_INCLUDED
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <boost/any/bad_any_cast.hpp>
#include <boost/any/fwd.hpp>
#include <boost/assert.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/type_index.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/throw_exception.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/core/addressof.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/conditional.hpp>
namespace boost {
namespace anys {
template <std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
class basic_any
{
BOOST_STATIC_ASSERT_MSG(OptimizeForSize > 0 && OptimizeForAlignment > 0, "Size and Align shall be positive values");
BOOST_STATIC_ASSERT_MSG(OptimizeForSize >= OptimizeForAlignment, "Size shall non less than Align");
BOOST_STATIC_ASSERT_MSG((OptimizeForAlignment & (OptimizeForAlignment - 1)) == 0, "Align shall be a power of 2");
BOOST_STATIC_ASSERT_MSG(OptimizeForSize % OptimizeForAlignment == 0, "Size shall be multiple of alignment");
private:
enum operation
{
Destroy,
Move,
Copy,
AnyCast,
UnsafeCast,
Typeinfo
};
template <typename ValueType>
static void* small_manager(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info)
{
switch (op)
{
case Destroy:
BOOST_ASSERT(!left.empty());
reinterpret_cast<ValueType*>(&left.content.small_value)->~ValueType();
break;
case Move: {
BOOST_ASSERT(left.empty());
BOOST_ASSERT(right);
BOOST_ASSERT(!right->empty());
BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
ValueType* value = reinterpret_cast<ValueType*>(&const_cast<basic_any*>(right)->content.small_value);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
new (&left.content.small_value) ValueType(std::move(*value));
#else
new (&left.content.small_value) ValueType(*value);
#endif
left.man = right->man;
reinterpret_cast<ValueType const*>(&right->content.small_value)->~ValueType();
const_cast<basic_any*>(right)->man = 0;
};
break;
case Copy:
BOOST_ASSERT(left.empty());
BOOST_ASSERT(right);
BOOST_ASSERT(!right->empty());
BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
new (&left.content.small_value) ValueType(*reinterpret_cast<const ValueType*>(&right->content.small_value));
left.man = right->man;
break;
case AnyCast:
BOOST_ASSERT(info);
BOOST_ASSERT(!left.empty());
return boost::typeindex::type_id<ValueType>() == *info ?
reinterpret_cast<typename remove_cv<ValueType>::type *>(&left.content.small_value) : 0;
case UnsafeCast:
BOOST_ASSERT(!left.empty());
return reinterpret_cast<typename remove_cv<ValueType>::type *>(&left.content.small_value);
case Typeinfo:
return const_cast<void*>(static_cast<const void*>(&boost::typeindex::type_id<ValueType>().type_info()));
}
return 0;
}
template <typename ValueType>
static void* large_manager(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info)
{
switch (op)
{
case Destroy:
BOOST_ASSERT(!left.empty());
delete static_cast<ValueType*>(left.content.large_value);
break;
case Move:
BOOST_ASSERT(left.empty());
BOOST_ASSERT(right);
BOOST_ASSERT(!right->empty());
BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
left.content.large_value = right->content.large_value;
left.man = right->man;
const_cast<basic_any*>(right)->content.large_value = 0;
const_cast<basic_any*>(right)->man = 0;
break;
case Copy:
BOOST_ASSERT(left.empty());
BOOST_ASSERT(right);
BOOST_ASSERT(!right->empty());
BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
left.content.large_value = new ValueType(*static_cast<const ValueType*>(right->content.large_value));
left.man = right->man;
break;
case AnyCast:
BOOST_ASSERT(info);
BOOST_ASSERT(!left.empty());
return boost::typeindex::type_id<ValueType>() == *info ?
static_cast<typename remove_cv<ValueType>::type *>(left.content.large_value) : 0;
case UnsafeCast:
BOOST_ASSERT(!left.empty());
return reinterpret_cast<typename remove_cv<ValueType>::type *>(left.content.large_value);
case Typeinfo:
return const_cast<void*>(static_cast<const void*>(&boost::typeindex::type_id<ValueType>().type_info()));
}
return 0;
}
template <typename ValueType>
struct is_small_object : boost::integral_constant<bool, sizeof(ValueType) <= OptimizeForSize &&
boost::alignment_of<ValueType>::value <= OptimizeForAlignment &&
boost::is_nothrow_move_constructible<ValueType>::value>
{};
template <typename ValueType>
static void create(basic_any& any, const ValueType& value, boost::true_type)
{
typedef typename boost::decay<const ValueType>::type DecayedType;
any.man = &small_manager<DecayedType>;
new (&any.content.small_value) ValueType(value);
}
template <typename ValueType>
static void create(basic_any& any, const ValueType& value, boost::false_type)
{
typedef typename boost::decay<const ValueType>::type DecayedType;
any.man = &large_manager<DecayedType>;
any.content.large_value = new DecayedType(value);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename ValueType>
static void create(basic_any& any, ValueType&& value, boost::true_type)
{
typedef typename boost::decay<const ValueType>::type DecayedType;
any.man = &small_manager<DecayedType>;
new (&any.content.small_value) DecayedType(static_cast<ValueType&&>(value));
}
template <typename ValueType>
static void create(basic_any& any, ValueType&& value, boost::false_type)
{
typedef typename boost::decay<const ValueType>::type DecayedType;
any.man = &large_manager<DecayedType>;
any.content.large_value = new DecayedType(static_cast<ValueType&&>(value));
}
#endif
public: // non-type template parameters accessors
static BOOST_CONSTEXPR_OR_CONST std::size_t buffer_size = OptimizeForSize;
static BOOST_CONSTEXPR_OR_CONST std::size_t buffer_align = OptimizeForAlignment;
public: // structors
BOOST_CONSTEXPR basic_any() BOOST_NOEXCEPT
: man(0), content()
{
}
template<typename ValueType>
basic_any(const ValueType & value)
: man(0), content()
{
BOOST_STATIC_ASSERT_MSG(
!(boost::is_same<ValueType, boost::any>::value),
"boost::anys::basic_any shall not be constructed from boost::any"
);
BOOST_STATIC_ASSERT_MSG(
!anys::detail::is_basic_any<ValueType>::value,
"boost::anys::basic_any<A, B> shall not be constructed from boost::anys::basic_any<C, D>"
);
create(*this, value, is_small_object<ValueType>());
}
basic_any(const basic_any & other)
: man(0), content()
{
if (other.man)
{
other.man(Copy, *this, &other, 0);
}
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move constructor
basic_any(basic_any&& other) BOOST_NOEXCEPT
: man(0), content()
{
if (other.man)
{
other.man(Move, *this, &other, 0);
}
}
// Perfect forwarding of ValueType
template<typename ValueType>
basic_any(ValueType&& value
, typename boost::disable_if<boost::is_same<basic_any&, ValueType> >::type* = 0 // disable if value has type `basic_any&`
, typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&`
: man(0), content()
{
typedef typename boost::decay<ValueType>::type DecayedType;
BOOST_STATIC_ASSERT_MSG(
!(boost::is_same<DecayedType, boost::any>::value),
"boost::anys::basic_any shall not be constructed from boost::any"
);
BOOST_STATIC_ASSERT_MSG(
!anys::detail::is_basic_any<DecayedType>::value,
"boost::anys::basic_any<A, B> shall not be constructed from boost::anys::basic_any<C, D>"
);
create(*this, static_cast<ValueType&&>(value), is_small_object<DecayedType>());
}
#endif
~basic_any() BOOST_NOEXCEPT
{
if (man)
{
man(Destroy, *this, 0, 0);
}
}
public: // modifiers
basic_any & swap(basic_any & rhs) BOOST_NOEXCEPT
{
if (this == &rhs)
{
return *this;
}
if (man && rhs.man)
{
basic_any tmp;
rhs.man(Move, tmp, &rhs, 0);
man(Move, rhs, this, 0);
tmp.man(Move, *this, &tmp, 0);
}
else if (man)
{
man(Move, rhs, this, 0);
}
else if (rhs.man)
{
rhs.man(Move, *this, &rhs, 0);
}
return *this;
}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename ValueType>
basic_any & operator=(const ValueType & rhs)
{
BOOST_STATIC_ASSERT_MSG(
!(boost::is_same<ValueType, boost::any>::value),
"boost::any shall not be assigned into boost::anys::basic_any"
);
BOOST_STATIC_ASSERT_MSG(
!anys::detail::is_basic_any<ValueType>::value,
"boost::anys::basic_any<A, B> shall not be assigned into boost::anys::basic_any<C, D>"
);
basic_any(rhs).swap(*this);
return *this;
}
basic_any & operator=(basic_any rhs)
{
rhs.swap(*this);
return *this;
}
#else
basic_any & operator=(const basic_any& rhs)
{
basic_any(rhs).swap(*this);
return *this;
}
// move assignment
basic_any & operator=(basic_any&& rhs) BOOST_NOEXCEPT
{
rhs.swap(*this);
basic_any().swap(rhs);
return *this;
}
// Perfect forwarding of ValueType
template <class ValueType>
basic_any & operator=(ValueType&& rhs)
{
typedef typename boost::decay<ValueType>::type DecayedType;
BOOST_STATIC_ASSERT_MSG(
!(boost::is_same<DecayedType, boost::any>::value),
"boost::any shall not be assigned into boost::anys::basic_any"
);
BOOST_STATIC_ASSERT_MSG(
(!anys::detail::is_basic_any<DecayedType>::value || boost::is_same<DecayedType, basic_any>::value),
"boost::anys::basic_any<A, B> shall not be assigned into boost::anys::basic_any<C, D>"
);
basic_any(static_cast<ValueType&&>(rhs)).swap(*this);
return *this;
}
#endif
public: // queries
bool empty() const BOOST_NOEXCEPT
{
return !man;
}
void clear() BOOST_NOEXCEPT
{
basic_any().swap(*this);
}
const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
{
return man
? *static_cast<const boost::typeindex::type_info*>(man(Typeinfo, const_cast<basic_any&>(*this), 0, 0))
: boost::typeindex::type_id<void>().type_info();
}
private: // representation
template<typename ValueType, std::size_t Size, std::size_t Alignment>
friend ValueType * any_cast(basic_any<Size, Alignment> *) BOOST_NOEXCEPT;
template<typename ValueType, std::size_t Size, std::size_t Alignment>
friend ValueType * unsafe_any_cast(basic_any<Size, Alignment> *) BOOST_NOEXCEPT;
typedef void*(*manager)(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info);
manager man;
union content {
void * large_value;
typename boost::aligned_storage<OptimizeForSize, OptimizeForAlignment>::type small_value;
} content;
};
template<std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
void swap(basic_any<OptimizeForSize, OptimizeForAlignment>& lhs, basic_any<OptimizeForSize, OptimizeForAlignment>& rhs) BOOST_NOEXCEPT
{
lhs.swap(rhs);
}
template<typename ValueType, std::size_t Size, std::size_t Alignment>
ValueType * any_cast(basic_any<Size, Alignment> * operand) BOOST_NOEXCEPT
{
return operand->man ?
static_cast<typename remove_cv<ValueType>::type *>(operand->man(basic_any<Size, Alignment>::AnyCast, *operand, 0, &boost::typeindex::type_id<ValueType>().type_info()))
: 0;
}
template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
inline const ValueType * any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> * operand) BOOST_NOEXCEPT
{
return any_cast<ValueType>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> *>(operand));
}
template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
ValueType any_cast(basic_any<OptimizeForSize, OptimizeForAlignment> & operand)
{
typedef typename remove_reference<ValueType>::type nonref;
nonref * result = any_cast<nonref>(boost::addressof(operand));
if(!result)
boost::throw_exception(bad_any_cast());
// Attempt to avoid construction of a temporary object in cases when
// `ValueType` is not a reference. Example:
// `static_cast<std::string>(*result);`
// which is equal to `std::string(*result);`
typedef typename boost::conditional<
boost::is_reference<ValueType>::value,
ValueType,
typename boost::add_reference<ValueType>::type
>::type ref_type;
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local!
#endif
return static_cast<ref_type>(*result);
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}
template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
inline ValueType any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> & operand)
{
typedef typename remove_reference<ValueType>::type nonref;
return any_cast<const nonref &>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> &>(operand));
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
inline ValueType any_cast(basic_any<OptimizeForSize, OptimizeForAlignment>&& operand)
{
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"
);
return any_cast<ValueType>(operand);
}
#endif
// Note: The "unsafe" versions of any_cast are not part of the
// public interface and may be removed at any time. They are
// required where we know what type is stored in the any and can't
// use typeid() comparison, e.g., when our types may travel across
// different shared libraries.
template<typename ValueType, std::size_t OptimizedForSize, std::size_t OptimizeForAlignment>
inline ValueType * unsafe_any_cast(basic_any<OptimizedForSize, OptimizeForAlignment> * operand) BOOST_NOEXCEPT
{
return static_cast<ValueType*>(operand->man(basic_any<OptimizedForSize, OptimizeForAlignment>::UnsafeCast, *operand, 0, 0));
}
template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
inline const ValueType * unsafe_any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> * operand) BOOST_NOEXCEPT
{
return unsafe_any_cast<ValueType>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> *>(operand));
}
} // namespace anys
using boost::anys::any_cast;
using boost::anys::unsafe_any_cast;
} // namespace boost
#endif // #ifndef BOOST_ANYS_BASIC_ANY_HPP_INCLUDED

40
sources/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

@ -4,12 +4,14 @@
// MS compatible compilers support #pragma once // MS compatible compilers support #pragma once
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma once # pragma once
#pragma inline_depth(511) #if !defined(__clang__)
#pragma inline_depth(255)
#pragma inline_recursion(on) #pragma inline_recursion(on)
#endif #endif
#endif
#if defined(__MWERKS__) #if defined(__MWERKS__)
#pragma inline_depth(511) #pragma inline_depth(255)
#endif #endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

View File

@ -2,14 +2,16 @@
#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
// MS compatible compilers support #pragma once // MS compatible compilers support #pragma once
#if defined(_MSC_VER) #if defined(BOOST_MSVC)
# pragma once # pragma once
#pragma inline_depth(511) #if !defined(__clang__)
#pragma inline_depth(255)
#pragma inline_recursion(on) #pragma inline_recursion(on)
#endif #endif
#endif
#if defined(__MWERKS__) #if defined(__MWERKS__)
#pragma inline_depth(511) #pragma inline_depth(255)
#endif #endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

View File

@ -4,12 +4,14 @@
// MS compatible compilers support #pragma once // MS compatible compilers support #pragma once
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma once # pragma once
#pragma inline_depth(511) #if !defined(__clang__)
#pragma inline_depth(255)
#pragma inline_recursion(on) #pragma inline_recursion(on)
#endif #endif
#endif
#if defined(__MWERKS__) #if defined(__MWERKS__)
#pragma inline_depth(511) #pragma inline_depth(255)
#endif #endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

View File

@ -112,8 +112,8 @@ basic_text_iprimitive<IStream>::basic_text_iprimitive(
) : ) :
is(is_), is(is_),
flags_saver(is_), flags_saver(is_),
precision_saver(is_),
#ifndef BOOST_NO_STD_LOCALE #ifndef BOOST_NO_STD_LOCALE
precision_saver(is_),
codecvt_null_facet(1), codecvt_null_facet(1),
archive_locale(is.getloc(), & codecvt_null_facet), archive_locale(is.getloc(), & codecvt_null_facet),
locale_saver(is) locale_saver(is)
@ -125,6 +125,7 @@ basic_text_iprimitive<IStream>::basic_text_iprimitive(
is_ >> std::noboolalpha; is_ >> std::noboolalpha;
} }
#else #else
precision_saver(is_)
{} {}
#endif #endif

View File

@ -87,8 +87,8 @@ basic_text_oprimitive<OStream>::basic_text_oprimitive(
) : ) :
os(os_), os(os_),
flags_saver(os_), flags_saver(os_),
precision_saver(os_),
#ifndef BOOST_NO_STD_LOCALE #ifndef BOOST_NO_STD_LOCALE
precision_saver(os_),
codecvt_null_facet(1), codecvt_null_facet(1),
archive_locale(os.getloc(), & codecvt_null_facet), archive_locale(os.getloc(), & codecvt_null_facet),
locale_saver(os) locale_saver(os)
@ -100,6 +100,7 @@ basic_text_oprimitive<OStream>::basic_text_oprimitive(
os_ << std::noboolalpha; os_ << std::noboolalpha;
} }
#else #else
precision_saver(os_)
{} {}
#endif #endif

View File

@ -2,7 +2,7 @@
// asio.hpp // asio.hpp
// ~~~~~~~~ // ~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -19,12 +19,17 @@
#include <boost/asio/associated_allocator.hpp> #include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp> #include <boost/asio/associated_executor.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp> #include <boost/asio/async_result.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/asio/basic_datagram_socket.hpp> #include <boost/asio/basic_datagram_socket.hpp>
#include <boost/asio/basic_deadline_timer.hpp> #include <boost/asio/basic_deadline_timer.hpp>
#include <boost/asio/basic_file.hpp>
#include <boost/asio/basic_io_object.hpp> #include <boost/asio/basic_io_object.hpp>
#include <boost/asio/basic_random_access_file.hpp>
#include <boost/asio/basic_raw_socket.hpp> #include <boost/asio/basic_raw_socket.hpp>
#include <boost/asio/basic_readable_pipe.hpp>
#include <boost/asio/basic_seq_packet_socket.hpp> #include <boost/asio/basic_seq_packet_socket.hpp>
#include <boost/asio/basic_serial_port.hpp> #include <boost/asio/basic_serial_port.hpp>
#include <boost/asio/basic_signal_set.hpp> #include <boost/asio/basic_signal_set.hpp>
@ -32,11 +37,15 @@
#include <boost/asio/basic_socket_acceptor.hpp> #include <boost/asio/basic_socket_acceptor.hpp>
#include <boost/asio/basic_socket_iostream.hpp> #include <boost/asio/basic_socket_iostream.hpp>
#include <boost/asio/basic_socket_streambuf.hpp> #include <boost/asio/basic_socket_streambuf.hpp>
#include <boost/asio/basic_stream_file.hpp>
#include <boost/asio/basic_stream_socket.hpp> #include <boost/asio/basic_stream_socket.hpp>
#include <boost/asio/basic_streambuf.hpp> #include <boost/asio/basic_streambuf.hpp>
#include <boost/asio/basic_waitable_timer.hpp> #include <boost/asio/basic_waitable_timer.hpp>
#include <boost/asio/basic_writable_pipe.hpp>
#include <boost/asio/bind_cancellation_slot.hpp>
#include <boost/asio/bind_executor.hpp> #include <boost/asio/bind_executor.hpp>
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#include <boost/asio/buffer_registration.hpp>
#include <boost/asio/buffered_read_stream_fwd.hpp> #include <boost/asio/buffered_read_stream_fwd.hpp>
#include <boost/asio/buffered_read_stream.hpp> #include <boost/asio/buffered_read_stream.hpp>
#include <boost/asio/buffered_stream_fwd.hpp> #include <boost/asio/buffered_stream_fwd.hpp>
@ -44,10 +53,14 @@
#include <boost/asio/buffered_write_stream_fwd.hpp> #include <boost/asio/buffered_write_stream_fwd.hpp>
#include <boost/asio/buffered_write_stream.hpp> #include <boost/asio/buffered_write_stream.hpp>
#include <boost/asio/buffers_iterator.hpp> #include <boost/asio/buffers_iterator.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/cancellation_state.hpp>
#include <boost/asio/cancellation_type.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/completion_condition.hpp> #include <boost/asio/completion_condition.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/connect.hpp> #include <boost/asio/connect.hpp>
#include <boost/asio/connect_pipe.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
#include <boost/asio/deadline_timer.hpp> #include <boost/asio/deadline_timer.hpp>
#include <boost/asio/defer.hpp> #include <boost/asio/defer.hpp>
@ -85,6 +98,7 @@
#include <boost/asio/execution_context.hpp> #include <boost/asio/execution_context.hpp>
#include <boost/asio/executor.hpp> #include <boost/asio/executor.hpp>
#include <boost/asio/executor_work_guard.hpp> #include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/file_base.hpp>
#include <boost/asio/generic/basic_endpoint.hpp> #include <boost/asio/generic/basic_endpoint.hpp>
#include <boost/asio/generic/datagram_protocol.hpp> #include <boost/asio/generic/datagram_protocol.hpp>
#include <boost/asio/generic/raw_protocol.hpp> #include <boost/asio/generic/raw_protocol.hpp>
@ -141,10 +155,13 @@
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <boost/asio/prefer.hpp> #include <boost/asio/prefer.hpp>
#include <boost/asio/query.hpp> #include <boost/asio/query.hpp>
#include <boost/asio/random_access_file.hpp>
#include <boost/asio/read.hpp> #include <boost/asio/read.hpp>
#include <boost/asio/read_at.hpp> #include <boost/asio/read_at.hpp>
#include <boost/asio/read_until.hpp> #include <boost/asio/read_until.hpp>
#include <boost/asio/readable_pipe.hpp>
#include <boost/asio/redirect_error.hpp> #include <boost/asio/redirect_error.hpp>
#include <boost/asio/registered_buffer.hpp>
#include <boost/asio/require.hpp> #include <boost/asio/require.hpp>
#include <boost/asio/require_concept.hpp> #include <boost/asio/require_concept.hpp>
#include <boost/asio/serial_port.hpp> #include <boost/asio/serial_port.hpp>
@ -154,6 +171,7 @@
#include <boost/asio/static_thread_pool.hpp> #include <boost/asio/static_thread_pool.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/asio/strand.hpp> #include <boost/asio/strand.hpp>
#include <boost/asio/stream_file.hpp>
#include <boost/asio/streambuf.hpp> #include <boost/asio/streambuf.hpp>
#include <boost/asio/system_context.hpp> #include <boost/asio/system_context.hpp>
#include <boost/asio/system_executor.hpp> #include <boost/asio/system_executor.hpp>
@ -175,6 +193,7 @@
#include <boost/asio/windows/overlapped_ptr.hpp> #include <boost/asio/windows/overlapped_ptr.hpp>
#include <boost/asio/windows/random_access_handle.hpp> #include <boost/asio/windows/random_access_handle.hpp>
#include <boost/asio/windows/stream_handle.hpp> #include <boost/asio/windows/stream_handle.hpp>
#include <boost/asio/writable_pipe.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <boost/asio/write_at.hpp> #include <boost/asio/write_at.hpp>

View File

@ -2,7 +2,7 @@
// any_io_executor.hpp // any_io_executor.hpp
// ~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -49,19 +49,245 @@ typedef executor any_io_executor;
* execution::prefer_only<execution::relationship_t::continuation_t> * execution::prefer_only<execution::relationship_t::continuation_t>
* > @endcode * > @endcode
*/ */
class any_io_executor :
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
typedef execution::any_executor<...> any_io_executor; public execution::any_executor<...>
#else // defined(GENERATING_DOCUMENTATION) #else // defined(GENERATING_DOCUMENTATION)
typedef execution::any_executor< public execution::any_executor<
execution::context_as_t<execution_context&>, execution::context_as_t<execution_context&>,
execution::blocking_t::never_t, execution::blocking_t::never_t,
execution::prefer_only<execution::blocking_t::possibly_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::tracked_t>,
execution::prefer_only<execution::outstanding_work_t::untracked_t>, execution::prefer_only<execution::outstanding_work_t::untracked_t>,
execution::prefer_only<execution::relationship_t::fork_t>, execution::prefer_only<execution::relationship_t::fork_t>,
execution::prefer_only<execution::relationship_t::continuation_t> execution::prefer_only<execution::relationship_t::continuation_t>
> any_io_executor; >
#endif // defined(GENERATING_DOCUMENTATION) #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) #endif // defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
@ -70,4 +296,10 @@ typedef execution::any_executor<
#include <boost/asio/detail/pop_options.hpp> #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 #endif // BOOST_ASIO_ANY_IO_EXECUTOR_HPP

View File

@ -2,7 +2,7 @@
// associated_allocator.hpp // associated_allocator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -17,15 +17,33 @@
#include <boost/asio/detail/config.hpp> #include <boost/asio/detail/config.hpp>
#include <memory> #include <memory>
#include <boost/asio/associator.hpp>
#include <boost/asio/detail/functional.hpp>
#include <boost/asio/detail/type_traits.hpp> #include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp> #include <boost/asio/detail/push_options.hpp>
namespace boost { namespace boost {
namespace asio { namespace asio {
template <typename T, typename Allocator>
struct associated_allocator;
namespace detail { namespace detail {
template <typename T, typename E, typename = void> template <typename T, typename = void>
struct has_allocator_type : false_type
{
};
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 struct associated_allocator_impl
{ {
typedef E type; typedef E type;
@ -48,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 } // namespace detail
/// Traits type used to obtain the allocator associated with an object. /// Traits type used to obtain the allocator associated with an object.
@ -119,6 +148,29 @@ using associated_allocator_t
#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) #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 asio
} // namespace boost } // 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 // associated_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -16,6 +16,8 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp> #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/detail/type_traits.hpp>
#include <boost/asio/execution/executor.hpp> #include <boost/asio/execution/executor.hpp>
#include <boost/asio/is_executor.hpp> #include <boost/asio/is_executor.hpp>
@ -25,9 +27,25 @@
namespace boost { namespace boost {
namespace asio { namespace asio {
template <typename T, typename Executor>
struct associated_executor;
namespace detail { namespace detail {
template <typename T, typename E, typename = void> template <typename T, typename = void>
struct has_executor_type : false_type
{
};
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 struct associated_executor_impl
{ {
typedef void asio_associated_executor_is_unspecialised; typedef void asio_associated_executor_is_unspecialised;
@ -52,6 +70,17 @@ struct associated_executor_impl<T, E,
} }
}; };
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 } // namespace detail
/// Traits type used to obtain the executor associated with an object. /// Traits type used to obtain the executor associated with an object.
@ -109,9 +138,9 @@ get_associated_executor(const T& t) BOOST_ASIO_NOEXCEPT
template <typename T, typename Executor> template <typename T, typename Executor>
inline typename associated_executor<T, Executor>::type inline typename associated_executor<T, Executor>::type
get_associated_executor(const T& t, const Executor& ex, get_associated_executor(const T& t, const Executor& ex,
typename enable_if< typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return associated_executor<T, Executor>::get(t, ex); return associated_executor<T, Executor>::get(t, ex);
} }
@ -125,8 +154,8 @@ template <typename T, typename ExecutionContext>
inline typename associated_executor<T, inline typename associated_executor<T,
typename ExecutionContext::executor_type>::type typename ExecutionContext::executor_type>::type
get_associated_executor(const T& t, ExecutionContext& ctx, get_associated_executor(const T& t, ExecutionContext& ctx,
typename enable_if<is_convertible<ExecutionContext&, typename constraint<is_convertible<ExecutionContext&,
execution_context&>::value>::type* = 0) BOOST_ASIO_NOEXCEPT execution_context&>::value>::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return associated_executor<T, return associated_executor<T,
typename ExecutionContext::executor_type>::get(t, ctx.get_executor()); typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
@ -160,6 +189,33 @@ struct associated_executor_forwarding_base<T, E,
}; };
} // namespace detail } // 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 asio
} // namespace boost } // namespace boost

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 @@
// awaitable.hpp // awaitable.hpp
// ~~~~~~~~~~~~~ // ~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -48,7 +48,7 @@ template <typename, typename> class awaitable_frame;
/// The return type of a coroutine or asynchronous operation. /// The return type of a coroutine or asynchronous operation.
template <typename T, typename Executor = any_io_executor> template <typename T, typename Executor = any_io_executor>
class awaitable class BOOST_ASIO_NODISCARD awaitable
{ {
public: public:
/// The type of the awaited value. /// The type of the awaited value.
@ -76,6 +76,14 @@ public:
frame_->destroy(); frame_->destroy();
} }
/// Move assignment.
awaitable& operator=(awaitable&& other) noexcept
{
if (this != &other)
frame_ = std::exchange(other.frame_, nullptr);
return *this;
}
/// Checks if the awaitable refers to a future result. /// Checks if the awaitable refers to a future result.
bool valid() const noexcept bool valid() const noexcept
{ {

View File

@ -2,7 +2,7 @@
// basic_datagram_socket.hpp // basic_datagram_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -46,6 +46,13 @@ class basic_datagram_socket;
* @par Thread Safety * @par Thread Safety
* @e Distinct @e objects: Safe.@n * @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe. * @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> template <typename Protocol, typename Executor>
class basic_datagram_socket class basic_datagram_socket
@ -101,9 +108,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_datagram_socket(ExecutionContext& context, explicit basic_datagram_socket(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context) : basic_socket<Protocol, Executor>(context)
{ {
} }
@ -139,9 +146,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context, basic_datagram_socket(ExecutionContext& context,
const protocol_type& protocol, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
>::type = defaulted_constraint())
: basic_socket<Protocol, Executor>(context, protocol) : basic_socket<Protocol, Executor>(context, protocol)
{ {
} }
@ -185,9 +193,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context, basic_datagram_socket(ExecutionContext& context,
const endpoint_type& endpoint, const endpoint_type& endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, endpoint) : basic_socket<Protocol, Executor>(context, endpoint)
{ {
} }
@ -230,9 +238,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_datagram_socket(ExecutionContext& context, basic_datagram_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket, const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket) : basic_socket<Protocol, Executor>(context, protocol, native_socket)
{ {
} }
@ -286,10 +294,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other, basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(std::move(other)) : basic_socket<Protocol, Executor>(std::move(other))
{ {
} }
@ -308,7 +316,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_datagram_socket& basic_datagram_socket&
@ -447,6 +455,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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. * @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 * Use the async_send_to function to send data on an unconnected datagram
* socket. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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 * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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 * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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 * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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. * @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 * Use the async_receive_from function to receive data on an unconnected
* datagram socket. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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 * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 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 * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,

View File

@ -2,7 +2,7 @@
// basic_deadline_timer.hpp // basic_deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -160,7 +160,7 @@ public:
* dispatch handlers for any asynchronous operations performed on the timer. * dispatch handlers for any asynchronous operations performed on the timer.
*/ */
explicit basic_deadline_timer(const executor_type& ex) explicit basic_deadline_timer(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -176,10 +176,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_deadline_timer(ExecutionContext& context, explicit basic_deadline_timer(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
} }
@ -194,7 +194,7 @@ public:
* as an absolute time. * as an absolute time.
*/ */
basic_deadline_timer(const executor_type& ex, const time_type& expiry_time) basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
@ -214,10 +214,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time, basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
@ -236,7 +236,7 @@ public:
*/ */
basic_deadline_timer(const executor_type& ex, basic_deadline_timer(const executor_type& ex,
const duration_type& expiry_time) const duration_type& expiry_time)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_from_now( impl_.get_service().expires_from_now(
@ -258,10 +258,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_deadline_timer(ExecutionContext& context, basic_deadline_timer(ExecutionContext& context,
const duration_type& expiry_time, const duration_type& expiry_time,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_from_now( impl_.get_service().expires_from_now(
@ -628,6 +628,16 @@ public:
* not, the handler will not be invoked from within this function. On * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))

View File

@ -0,0 +1,831 @@
//
// basic_file.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_BASIC_FILE_HPP
#define BOOST_ASIO_BASIC_FILE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_FILE) \
|| defined(GENERATING_DOCUMENTATION)
#include <string>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/io_object_impl.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/execution_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/file_base.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_file_service.hpp>
#elif defined(BOOST_ASIO_HAS_IO_URING)
# include <boost/asio/detail/io_uring_file_service.hpp>
#endif
#if defined(BOOST_ASIO_HAS_MOVE)
# include <utility>
#endif // defined(BOOST_ASIO_HAS_MOVE)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
#if !defined(BOOST_ASIO_BASIC_FILE_FWD_DECL)
#define BOOST_ASIO_BASIC_FILE_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Executor = any_io_executor>
class basic_file;
#endif // !defined(BOOST_ASIO_BASIC_FILE_FWD_DECL)
/// Provides file functionality.
/**
* The basic_file class template provides functionality that is common to both
* stream-oriented and random-access files.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Executor>
class basic_file
: public file_base
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the file type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The file type when rebound to the specified executor.
typedef basic_file<Executor1> other;
};
/// The native representation of a file.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#elif defined(BOOST_ASIO_HAS_IOCP)
typedef detail::win_iocp_file_service::native_handle_type native_handle_type;
#elif defined(BOOST_ASIO_HAS_IO_URING)
typedef detail::io_uring_file_service::native_handle_type native_handle_type;
#endif
/// Construct a basic_file without opening it.
/**
* This constructor initialises a file without opening it.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*/
explicit basic_file(const executor_type& ex)
: impl_(0, ex)
{
}
/// Construct a basic_file without opening it.
/**
* This constructor initialises a file without opening it.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*/
template <typename ExecutionContext>
explicit basic_file(ExecutionContext& context,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: impl_(0, 0, context)
{
}
/// Construct and open a basic_file.
/**
* This constructor initialises a file and opens it.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*/
explicit basic_file(const executor_type& ex,
const char* path, file_base::flags open_flags)
: impl_(0, ex)
{
boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct a basic_file without opening it.
/**
* This constructor initialises a file and opens it.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*/
template <typename ExecutionContext>
explicit basic_file(ExecutionContext& context,
const char* path, file_base::flags open_flags,
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(), path, open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_file.
/**
* This constructor initialises a file and opens it.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*/
explicit basic_file(const executor_type& ex,
const std::string& path, file_base::flags open_flags)
: impl_(0, ex)
{
boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(),
path.c_str(), open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct a basic_file without opening it.
/**
* This constructor initialises a file and opens it.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*/
template <typename ExecutionContext>
explicit basic_file(ExecutionContext& context,
const std::string& path, file_base::flags open_flags,
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(),
path.c_str(), open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct a basic_file on an existing native file handle.
/**
* This constructor initialises a file object to hold an existing native file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param native_file A native file handle.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_file(const executor_type& ex, const native_handle_type& native_file)
: impl_(0, ex)
{
boost::system::error_code ec;
impl_.get_service().assign(
impl_.get_implementation(), native_file, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Construct a basic_file on an existing native file.
/**
* This constructor initialises a file object to hold an existing native file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param native_file A native file.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_file(ExecutionContext& context, const native_handle_type& native_file,
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().assign(
impl_.get_implementation(), native_file, ec);
boost::asio::detail::throw_error(ec, "assign");
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_file from another.
/**
* This constructor moves a file from one object to another.
*
* @param other The other basic_file object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_file(const executor_type&) constructor.
*/
basic_file(basic_file&& other) BOOST_ASIO_NOEXCEPT
: impl_(std::move(other.impl_))
{
}
/// Move-assign a basic_file from another.
/**
* This assignment operator moves a file from one object to another.
*
* @param other The other basic_file object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_file(const executor_type&) constructor.
*/
basic_file& operator=(basic_file&& other)
{
impl_ = std::move(other.impl_);
return *this;
}
// All files have access to each other's implementations.
template <typename Executor1>
friend class basic_file;
/// Move-construct a basic_file from a file of another executor type.
/**
* This constructor moves a file from one object to another.
*
* @param other The other basic_file object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_file(const executor_type&) constructor.
*/
template <typename Executor1>
basic_file(basic_file<Executor1>&& other,
typename constraint<
is_convertible<Executor1, Executor>::value,
defaulted_constraint
>::type = defaulted_constraint())
: impl_(std::move(other.impl_))
{
}
/// Move-assign a basic_file from a file of another executor type.
/**
* This assignment operator moves a file from one object to another.
*
* @param other The other basic_file object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_file(const executor_type&) constructor.
*/
template <typename Executor1>
typename constraint<
is_convertible<Executor1, Executor>::value,
basic_file&
>::type operator=(basic_file<Executor1> && other)
{
basic_file tmp(std::move(other));
impl_ = std::move(tmp.impl_);
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Get the executor associated with the object.
executor_type get_executor() BOOST_ASIO_NOEXCEPT
{
return impl_.get_executor();
}
/// Open the file using the specified path.
/**
* This function opens the file so that it will use the specified path.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*
* @par Example
* @code
* boost::asio::stream_file file(my_context);
* file.open("/path/to/my/file", boost::asio::stream_file::read_only);
* @endcode
*/
void open(const char* path, file_base::flags open_flags)
{
boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Open the file using the specified path.
/**
* This function opens the file so that it will use the specified path.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* boost::asio::stream_file file(my_context);
* boost::system::error_code ec;
* file.open("/path/to/my/file", boost::asio::stream_file::read_only, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
BOOST_ASIO_SYNC_OP_VOID open(const char* path,
file_base::flags open_flags, boost::system::error_code& ec)
{
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Open the file using the specified path.
/**
* This function opens the file so that it will use the specified path.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*
* @par Example
* @code
* boost::asio::stream_file file(my_context);
* file.open("/path/to/my/file", boost::asio::stream_file::read_only);
* @endcode
*/
void open(const std::string& path, file_base::flags open_flags)
{
boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(),
path.c_str(), open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Open the file using the specified path.
/**
* This function opens the file so that it will use the specified path.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @param ec Set to indicate what error occurred, if any.
*
* @par Example
* @code
* boost::asio::stream_file file(my_context);
* boost::system::error_code ec;
* file.open("/path/to/my/file", boost::asio::stream_file::read_only, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
BOOST_ASIO_SYNC_OP_VOID open(const std::string& path,
file_base::flags open_flags, boost::system::error_code& ec)
{
impl_.get_service().open(impl_.get_implementation(),
path.c_str(), open_flags, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native file to the file.
/*
* This function opens the file to hold an existing native file.
*
* @param native_file A native file.
*
* @throws boost::system::system_error Thrown on failure.
*/
void assign(const native_handle_type& native_file)
{
boost::system::error_code ec;
impl_.get_service().assign(
impl_.get_implementation(), native_file, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Assign an existing native file to the file.
/*
* This function opens the file to hold an existing native file.
*
* @param native_file A native file.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_file,
boost::system::error_code& ec)
{
impl_.get_service().assign(
impl_.get_implementation(), native_file, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the file is open.
bool is_open() const
{
return impl_.get_service().is_open(impl_.get_implementation());
}
/// Close the file.
/**
* This function is used to close the file. Any asynchronous read or write
* operations will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure. Note that, even if
* the function indicates an error, the underlying descriptor is closed.
*/
void close()
{
boost::system::error_code ec;
impl_.get_service().close(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "close");
}
/// Close the file.
/**
* This function is used to close the file. Any asynchronous read or write
* operations will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any. Note that, even if
* the function indicates an error, the underlying descriptor is closed.
*
* @par Example
* @code
* boost::asio::stream_file file(my_context);
* ...
* boost::system::error_code ec;
* file.close(ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
impl_.get_service().close(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Release ownership of the underlying native file.
/**
* This function causes all outstanding asynchronous read and write
* operations to finish immediately, and the handlers for cancelled
* operations will be passed the boost::asio::error::operation_aborted error.
* Ownership of the native file is then transferred to the caller.
*
* @throws boost::system::system_error Thrown on failure.
*
* @note This function is unsupported on Windows versions prior to Windows
* 8.1, and will fail with boost::asio::error::operation_not_supported on
* these platforms.
*/
#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
__declspec(deprecated("This function always fails with "
"operation_not_supported when used on Windows versions "
"prior to Windows 8.1."))
#endif
native_handle_type release()
{
boost::system::error_code ec;
native_handle_type s = impl_.get_service().release(
impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "release");
return s;
}
/// Release ownership of the underlying native file.
/**
* This function causes all outstanding asynchronous read and write
* operations to finish immediately, and the handlers for cancelled
* operations will be passed the boost::asio::error::operation_aborted error.
* Ownership of the native file is then transferred to the caller.
*
* @param ec Set to indicate what error occurred, if any.
*
* @note This function is unsupported on Windows versions prior to Windows
* 8.1, and will fail with boost::asio::error::operation_not_supported on
* these platforms.
*/
#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
__declspec(deprecated("This function always fails with "
"operation_not_supported when used on Windows versions "
"prior to Windows 8.1."))
#endif
native_handle_type release(boost::system::error_code& ec)
{
return impl_.get_service().release(impl_.get_implementation(), ec);
}
/// Get the native file representation.
/**
* This function may be used to obtain the underlying representation of the
* file. This is intended to allow access to native file functionality
* that is not otherwise provided.
*/
native_handle_type native_handle()
{
return impl_.get_service().native_handle(impl_.get_implementation());
}
/// Cancel all asynchronous operations associated with the file.
/**
* This function causes all outstanding asynchronous read and write
* operations to finish immediately, and the handlers for cancelled
* operations will be passed the boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure.
*
* @note Calls to cancel() will always fail with
* boost::asio::error::operation_not_supported when run on Windows XP, Windows
* Server 2003, and earlier versions of Windows, unless
* BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
* two issues that should be considered before enabling its use:
*
* @li It will only cancel asynchronous operations that were initiated in the
* current thread.
*
* @li It can appear to complete without error, but the request to cancel the
* unfinished operations may be silently ignored by the operating system.
* Whether it works or not seems to depend on the drivers that are installed.
*
* For portable cancellation, consider using the close() function to
* simultaneously cancel the outstanding operations and close the file.
*
* When running on Windows Vista, Windows Server 2008, and later, the
* CancelIoEx function is always used. This function does not have the
* problems described above.
*/
#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
&& !defined(BOOST_ASIO_ENABLE_CANCELIO)
__declspec(deprecated("By default, this function always fails with "
"operation_not_supported when used on Windows XP, Windows Server 2003, "
"or earlier. Consult documentation for details."))
#endif
void cancel()
{
boost::system::error_code ec;
impl_.get_service().cancel(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
}
/// Cancel all asynchronous operations associated with the file.
/**
* This function causes all outstanding asynchronous read and write
* operations to finish immediately, and the handlers for cancelled
* operations will be passed the boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*
* @note Calls to cancel() will always fail with
* boost::asio::error::operation_not_supported when run on Windows XP, Windows
* Server 2003, and earlier versions of Windows, unless
* BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
* two issues that should be considered before enabling its use:
*
* @li It will only cancel asynchronous operations that were initiated in the
* current thread.
*
* @li It can appear to complete without error, but the request to cancel the
* unfinished operations may be silently ignored by the operating system.
* Whether it works or not seems to depend on the drivers that are installed.
*
* For portable cancellation, consider using the close() function to
* simultaneously cancel the outstanding operations and close the file.
*
* When running on Windows Vista, Windows Server 2008, and later, the
* CancelIoEx function is always used. This function does not have the
* problems described above.
*/
#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
&& !defined(BOOST_ASIO_ENABLE_CANCELIO)
__declspec(deprecated("By default, this function always fails with "
"operation_not_supported when used on Windows XP, Windows Server 2003, "
"or earlier. Consult documentation for details."))
#endif
BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
impl_.get_service().cancel(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the size of the file.
/**
* This function determines the size of the file, in bytes.
*
* @throws boost::system::system_error Thrown on failure.
*/
uint64_t size() const
{
boost::system::error_code ec;
uint64_t s = impl_.get_service().size(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "size");
return s;
}
/// Get the size of the file.
/**
* This function determines the size of the file, in bytes.
*
* @param ec Set to indicate what error occurred, if any.
*/
uint64_t size(boost::system::error_code& ec) const
{
return impl_.get_service().size(impl_.get_implementation(), ec);
}
/// Alter the size of the file.
/**
* This function resizes the file to the specified size, in bytes. If the
* current file size exceeds @c n then any extra data is discarded. If the
* current size is less than @c n then the file is extended and filled with
* zeroes.
*
* @param n The new size for the file.
*
* @throws boost::system::system_error Thrown on failure.
*/
void resize(uint64_t n)
{
boost::system::error_code ec;
impl_.get_service().resize(impl_.get_implementation(), n, ec);
boost::asio::detail::throw_error(ec, "resize");
}
/// Alter the size of the file.
/**
* This function resizes the file to the specified size, in bytes. If the
* current file size exceeds @c n then any extra data is discarded. If the
* current size is less than @c n then the file is extended and filled with
* zeroes.
*
* @param n The new size for the file.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID resize(uint64_t n, boost::system::error_code& ec)
{
impl_.get_service().resize(impl_.get_implementation(), n, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Synchronise the file to disk.
/**
* This function synchronises the file data and metadata to disk. Note that
* the semantics of this synchronisation vary between operation systems.
*
* @throws boost::system::system_error Thrown on failure.
*/
void sync_all()
{
boost::system::error_code ec;
impl_.get_service().sync_all(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "sync_all");
}
/// Synchronise the file to disk.
/**
* This function synchronises the file data and metadata to disk. Note that
* the semantics of this synchronisation vary between operation systems.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID sync_all(boost::system::error_code& ec)
{
impl_.get_service().sync_all(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Synchronise the file data to disk.
/**
* This function synchronises the file data to disk. Note that the semantics
* of this synchronisation vary between operation systems.
*
* @throws boost::system::system_error Thrown on failure.
*/
void sync_data()
{
boost::system::error_code ec;
impl_.get_service().sync_data(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "sync_data");
}
/// Synchronise the file data to disk.
/**
* This function synchronises the file data to disk. Note that the semantics
* of this synchronisation vary between operation systems.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID sync_data(boost::system::error_code& ec)
{
impl_.get_service().sync_data(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
protected:
/// Protected destructor to prevent deletion through this type.
/**
* This function destroys the file, cancelling any outstanding asynchronous
* operations associated with the file as if by calling @c cancel.
*/
~basic_file()
{
}
#if defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl<detail::win_iocp_file_service, Executor> impl_;
#elif defined(BOOST_ASIO_HAS_IO_URING)
detail::io_object_impl<detail::io_uring_file_service, Executor> impl_;
#endif
private:
// Disallow copying and assignment.
basic_file(const basic_file&) BOOST_ASIO_DELETED;
basic_file& operator=(const basic_file&) BOOST_ASIO_DELETED;
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_FILE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_BASIC_FILE_HPP

View File

@ -2,7 +2,7 @@
// basic_io_object.hpp // basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -0,0 +1,679 @@
//
// basic_random_access_file.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_BASIC_RANDOM_ACCESS_FILE_HPP
#define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_FILE) \
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_file.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
#if !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
#define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Executor = any_io_executor>
class basic_random_access_file;
#endif // !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
/// Provides random-access file functionality.
/**
* The basic_random_access_file class template provides asynchronous and
* blocking random-access file functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* Synchronous @c read_some_at and @c write_some_at 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 file object. Other
* synchronous operations, such as @c open or @c close, are not thread safe.
*/
template <typename Executor>
class basic_random_access_file
: public basic_file<Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the file type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The file type when rebound to the specified executor.
typedef basic_random_access_file<Executor1> other;
};
/// The native representation of a file.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_file<Executor>::native_handle_type native_handle_type;
#endif
/// Construct a basic_random_access_file without opening it.
/**
* This constructor initialises a file without opening it. The file needs to
* be opened before data can be read from or or written to it.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*/
explicit basic_random_access_file(const executor_type& ex)
: basic_file<Executor>(ex)
{
}
/// Construct a basic_random_access_file without opening it.
/**
* This constructor initialises a file without opening it. The file needs to
* be opened before data can be read from or or written to it.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*/
template <typename ExecutionContext>
explicit basic_random_access_file(ExecutionContext& context,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context)
{
}
/// Construct and open a basic_random_access_file.
/**
* This constructor initialises and opens a file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_random_access_file(const executor_type& ex,
const char* path, file_base::flags open_flags)
: basic_file<Executor>(ex, path, open_flags)
{
}
/// Construct and open a basic_random_access_file.
/**
* This constructor initialises and opens a file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_random_access_file(ExecutionContext& context,
const char* path, file_base::flags open_flags,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context, path, open_flags)
{
}
/// Construct and open a basic_random_access_file.
/**
* This constructor initialises and opens a file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_random_access_file(const executor_type& ex,
const std::string& path, file_base::flags open_flags)
: basic_file<Executor>(ex, path, open_flags)
{
}
/// Construct and open a basic_random_access_file.
/**
* This constructor initialises and opens a file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_random_access_file(ExecutionContext& context,
const std::string& path, file_base::flags open_flags,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context, path, open_flags)
{
}
/// Construct a basic_random_access_file on an existing native file.
/**
* This constructor initialises a random-access file object to hold an
* existing native file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param native_file The new underlying file implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_random_access_file(const executor_type& ex,
const native_handle_type& native_file)
: basic_file<Executor>(ex, native_file)
{
}
/// Construct a basic_random_access_file on an existing native file.
/**
* This constructor initialises a random-access file object to hold an
* existing native file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param native_file The new underlying file implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_random_access_file(ExecutionContext& context,
const native_handle_type& native_file,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context, native_file)
{
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_random_access_file from another.
/**
* This constructor moves a random-access file from one object to another.
*
* @param other The other basic_random_access_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_random_access_file(const executor_type&)
* constructor.
*/
basic_random_access_file(basic_random_access_file&& other) BOOST_ASIO_NOEXCEPT
: basic_file<Executor>(std::move(other))
{
}
/// Move-assign a basic_random_access_file from another.
/**
* This assignment operator moves a random-access file from one object to
* another.
*
* @param other The other basic_random_access_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_random_access_file(const executor_type&)
* constructor.
*/
basic_random_access_file& operator=(basic_random_access_file&& other)
{
basic_file<Executor>::operator=(std::move(other));
return *this;
}
/// Move-construct a basic_random_access_file from a file of another executor
/// type.
/**
* This constructor moves a random-access file from one object to another.
*
* @param other The other basic_random_access_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_random_access_file(const executor_type&)
* constructor.
*/
template <typename Executor1>
basic_random_access_file(basic_random_access_file<Executor1>&& other,
typename constraint<
is_convertible<Executor1, Executor>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(std::move(other))
{
}
/// Move-assign a basic_random_access_file from a file of another executor
/// type.
/**
* This assignment operator moves a random-access file from one object to
* another.
*
* @param other The other basic_random_access_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_random_access_file(const executor_type&)
* constructor.
*/
template <typename Executor1>
typename constraint<
is_convertible<Executor1, Executor>::value,
basic_random_access_file&
>::type operator=(basic_random_access_file<Executor1>&& other)
{
basic_file<Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroys the file.
/**
* This function destroys the file, cancelling any outstanding asynchronous
* operations associated with the file as if by calling @c cancel.
*/
~basic_random_access_file()
{
}
/// Write some data to the handle at the specified offset.
/**
* This function is used to write data to the random-access handle. The
* function call will block until one or more bytes of the data has been
* written successfully, or until an error occurs.
*
* @param offset The offset at which the data will be written.
*
* @param buffers One or more data buffers to be written to the handle.
*
* @returns The number of bytes written.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the end of the file was reached.
*
* @note The write_some_at operation may not write all of the data. Consider
* using the @ref write_at function if you need to ensure that all data is
* written before the blocking operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* handle.write_some_at(42, boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t write_some_at(uint64_t offset,
const ConstBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = this->impl_.get_service().write_some_at(
this->impl_.get_implementation(), offset, buffers, ec);
boost::asio::detail::throw_error(ec, "write_some_at");
return s;
}
/// Write some data to the handle at the specified offset.
/**
* This function is used to write data to the random-access handle. The
* function call will block until one or more bytes of the data has been
* written successfully, or until an error occurs.
*
* @param offset The offset at which the data will be written.
*
* @param buffers One or more data buffers to be written to the handle.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes written. Returns 0 if an error occurred.
*
* @note The write_some operation may not write all of the data to the
* file. Consider using the @ref write_at function if you need to ensure that
* all data is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t write_some_at(uint64_t offset,
const ConstBufferSequence& buffers, boost::system::error_code& ec)
{
return this->impl_.get_service().write_some_at(
this->impl_.get_implementation(), offset, buffers, ec);
}
/// Start an asynchronous write at the specified offset.
/**
* This function is used to asynchronously write data to the random-access
* handle. The function call always returns immediately.
*
* @param offset The offset at which the data will be written.
*
* @param buffers One or more data buffers to be written to the handle.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The write operation may not write all of the data to the file.
* Consider using the @ref async_write_at function if you need to ensure that
* all data is written before the asynchronous operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* handle.async_write_some_at(42, boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*
* @par Per-Operation Cancellation
* 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,
std::size_t)) WriteHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write_some_at(uint64_t offset,
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_write_some_at(this), handler, offset, buffers);
}
/// Read some data from the handle at the specified offset.
/**
* This function is used to read data from the random-access handle. The
* function call will block until one or more bytes of data has been read
* successfully, or until an error occurs.
*
* @param offset The offset at which the data will be read.
*
* @param buffers One or more buffers into which the data will be read.
*
* @returns The number of bytes read.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the end of the file was reached.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read_at function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* handle.read_some_at(42, boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t read_some_at(uint64_t offset,
const MutableBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = this->impl_.get_service().read_some_at(
this->impl_.get_implementation(), offset, buffers, ec);
boost::asio::detail::throw_error(ec, "read_some_at");
return s;
}
/// Read some data from the handle at the specified offset.
/**
* This function is used to read data from the random-access handle. The
* function call will block until one or more bytes of data has been read
* successfully, or until an error occurs.
*
* @param offset The offset at which the data will be read.
*
* @param buffers One or more buffers into which the data will be read.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes read. Returns 0 if an error occurred.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read_at function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*/
template <typename MutableBufferSequence>
std::size_t read_some_at(uint64_t offset,
const MutableBufferSequence& buffers, boost::system::error_code& ec)
{
return this->impl_.get_service().read_some_at(
this->impl_.get_implementation(), offset, buffers, ec);
}
/// Start an asynchronous read at the specified offset.
/**
* This function is used to asynchronously read data from the random-access
* handle. The function call always returns immediately.
*
* @param offset The offset at which the data will be read.
*
* @param buffers One or more buffers into which the data will be read.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read_at function if you need to ensure that
* the requested amount of data is read before the asynchronous operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* handle.async_read_some_at(42, boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*
* @par Per-Operation Cancellation
* 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,
std::size_t)) ReadHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_some_at(uint64_t offset,
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_read_some_at(this), handler, offset, buffers);
}
private:
// Disallow copying and assignment.
basic_random_access_file(const basic_random_access_file&) BOOST_ASIO_DELETED;
basic_random_access_file& operator=(
const basic_random_access_file&) BOOST_ASIO_DELETED;
class initiate_async_write_some_at
{
public:
typedef Executor executor_type;
explicit initiate_async_write_some_at(basic_random_access_file* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
uint64_t offset, const ConstBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self_->impl_.get_service().async_write_some_at(
self_->impl_.get_implementation(), offset, buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_random_access_file* self_;
};
class initiate_async_read_some_at
{
public:
typedef Executor executor_type;
explicit initiate_async_read_some_at(basic_random_access_file* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
uint64_t offset, const MutableBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self_->impl_.get_service().async_read_some_at(
self_->impl_.get_implementation(), offset, buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_random_access_file* self_;
};
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_FILE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP

View File

@ -2,7 +2,7 @@
// basic_raw_socket.hpp // basic_raw_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -46,6 +46,13 @@ class basic_raw_socket;
* @par Thread Safety * @par Thread Safety
* @e Distinct @e objects: Safe.@n * @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe. * @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> template <typename Protocol, typename Executor>
class basic_raw_socket class basic_raw_socket
@ -101,9 +108,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_raw_socket(ExecutionContext& context, explicit basic_raw_socket(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context) : basic_socket<Protocol, Executor>(context)
{ {
} }
@ -138,9 +145,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context, const protocol_type& protocol, basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
>::type = defaulted_constraint())
: basic_socket<Protocol, Executor>(context, protocol) : basic_socket<Protocol, Executor>(context, protocol)
{ {
} }
@ -183,9 +191,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint, basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, endpoint) : basic_socket<Protocol, Executor>(context, endpoint)
{ {
} }
@ -228,9 +236,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_raw_socket(ExecutionContext& context, basic_raw_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket, const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket) : basic_socket<Protocol, Executor>(context, protocol, native_socket)
{ {
} }
@ -283,10 +291,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other, basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(std::move(other)) : basic_socket<Protocol, Executor>(std::move(other))
{ {
} }
@ -303,7 +311,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_raw_socket& basic_raw_socket&
@ -439,6 +447,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -483,6 +501,16 @@ public:
* @note The async_send operation can only be used with a connected socket. * @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 raw * Use the async_send_to function to send data on an unconnected raw
* socket. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -624,6 +652,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -668,6 +706,16 @@ public:
* not, the handler will not be invoked from within this function. On * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -809,6 +857,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -853,6 +911,16 @@ public:
* @note The async_receive operation can only be used with a connected socket. * @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 * Use the async_receive_from function to receive data on an unconnected
* raw socket. * raw 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -994,6 +1062,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -1040,6 +1118,16 @@ public:
* not, the handler will not be invoked from within this function. On * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,

View File

@ -0,0 +1,525 @@
//
// basic_readable_pipe.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_BASIC_READABLE_PIPE_HPP
#define BOOST_ASIO_BASIC_READABLE_PIPE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_PIPE) \
|| defined(GENERATING_DOCUMENTATION)
#include <string>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/io_object_impl.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/execution_context.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_handle_service.hpp>
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
# include <boost/asio/detail/io_uring_descriptor_service.hpp>
#else
# include <boost/asio/detail/reactive_descriptor_service.hpp>
#endif
#if defined(BOOST_ASIO_HAS_MOVE)
# include <utility>
#endif // defined(BOOST_ASIO_HAS_MOVE)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
/// Provides pipe functionality.
/**
* The basic_readable_pipe class provides a wrapper over pipe
* functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Executor = any_io_executor>
class basic_readable_pipe
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the pipe type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The pipe type when rebound to the specified executor.
typedef basic_readable_pipe<Executor1> other;
};
/// The native representation of a pipe.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#elif defined(BOOST_ASIO_HAS_IOCP)
typedef detail::win_iocp_handle_service::native_handle_type
native_handle_type;
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
typedef detail::io_uring_descriptor_service::native_handle_type
native_handle_type;
#else
typedef detail::reactive_descriptor_service::native_handle_type
native_handle_type;
#endif
/// A basic_readable_pipe is always the lowest layer.
typedef basic_readable_pipe lowest_layer_type;
/// Construct a basic_readable_pipe without opening it.
/**
* This constructor creates a pipe without opening it.
*
* @param ex The I/O executor that the pipe will use, by default, to dispatch
* handlers for any asynchronous operations performed on the pipe.
*/
explicit basic_readable_pipe(const executor_type& ex)
: impl_(0, ex)
{
}
/// Construct a basic_readable_pipe without opening it.
/**
* This constructor creates a pipe without opening it.
*
* @param context An execution context which provides the I/O executor that
* the pipe will use, by default, to dispatch handlers for any asynchronous
* operations performed on the pipe.
*/
template <typename ExecutionContext>
explicit basic_readable_pipe(ExecutionContext& context,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: impl_(0, 0, context)
{
}
/// Construct a basic_readable_pipe on an existing native pipe.
/**
* This constructor creates a pipe object to hold an existing native
* pipe.
*
* @param ex The I/O executor that the pipe will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_readable_pipe(const executor_type& ex,
const native_handle_type& native_pipe)
: impl_(0, ex)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(),
native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Construct a basic_readable_pipe on an existing native pipe.
/**
* This constructor creates a pipe object to hold an existing native
* pipe.
*
* @param context An execution context which provides the I/O executor that
* the pipe will use, by default, to dispatch handlers for any
* asynchronous operations performed on the pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_readable_pipe(ExecutionContext& context,
const native_handle_type& native_pipe,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type = 0)
: impl_(0, 0, context)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(),
native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_readable_pipe from another.
/**
* This constructor moves a pipe from one object to another.
*
* @param other The other basic_readable_pipe object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_readable_pipe(const executor_type&)
* constructor.
*/
basic_readable_pipe(basic_readable_pipe&& other)
: impl_(std::move(other.impl_))
{
}
/// Move-assign a basic_readable_pipe from another.
/**
* This assignment operator moves a pipe from one object to another.
*
* @param other The other basic_readable_pipe object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_readable_pipe(const executor_type&)
* constructor.
*/
basic_readable_pipe& operator=(basic_readable_pipe&& other)
{
impl_ = std::move(other.impl_);
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroys the pipe.
/**
* This function destroys the pipe, cancelling any outstanding
* asynchronous wait operations associated with the pipe as if by
* calling @c cancel.
*/
~basic_readable_pipe()
{
}
/// Get the executor associated with the object.
executor_type get_executor() BOOST_ASIO_NOEXCEPT
{
return impl_.get_executor();
}
/// Get a reference to the lowest layer.
/**
* This function returns a reference to the lowest layer in a stack of
* layers. Since a basic_readable_pipe cannot contain any further layers, it
* simply returns a reference to itself.
*
* @return A reference to the lowest layer in the stack of layers. Ownership
* is not transferred to the caller.
*/
lowest_layer_type& lowest_layer()
{
return *this;
}
/// Get a const reference to the lowest layer.
/**
* This function returns a const reference to the lowest layer in a stack of
* layers. Since a basic_readable_pipe cannot contain any further layers, it
* simply returns a reference to itself.
*
* @return A const reference to the lowest layer in the stack of layers.
* Ownership is not transferred to the caller.
*/
const lowest_layer_type& lowest_layer() const
{
return *this;
}
/// Assign an existing native pipe to the pipe.
/*
* This function opens the pipe to hold an existing native pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
void assign(const native_handle_type& native_pipe)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Assign an existing native pipe to the pipe.
/*
* This function opens the pipe to hold an existing native pipe.
*
* @param native_pipe A native pipe.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,
boost::system::error_code& ec)
{
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the pipe is open.
bool is_open() const
{
return impl_.get_service().is_open(impl_.get_implementation());
}
/// Close the pipe.
/**
* This function is used to close the pipe. Any asynchronous read operations
* will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure.
*/
void close()
{
boost::system::error_code ec;
impl_.get_service().close(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "close");
}
/// Close the pipe.
/**
* This function is used to close the pipe. Any asynchronous read operations
* will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
impl_.get_service().close(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native pipe representation.
/**
* This function may be used to obtain the underlying representation of the
* pipe. This is intended to allow access to native pipe
* functionality that is not otherwise provided.
*/
native_handle_type native_handle()
{
return impl_.get_service().native_handle(impl_.get_implementation());
}
/// Cancel all asynchronous operations associated with the pipe.
/**
* This function causes all outstanding asynchronous read operations to finish
* immediately, and the handlers for cancelled operations will be passed the
* boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure.
*/
void cancel()
{
boost::system::error_code ec;
impl_.get_service().cancel(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
}
/// Cancel all asynchronous operations associated with the pipe.
/**
* This function causes all outstanding asynchronous read operations to finish
* immediately, and the handlers for cancelled operations will be passed the
* boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
impl_.get_service().cancel(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Read some data from the pipe.
/**
* This function is used to read data from the pipe. The function call will
* block until one or more bytes of data has been read successfully, or until
* an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @returns The number of bytes read.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* basic_readable_pipe.read_some(boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = impl_.get_service().read_some(
impl_.get_implementation(), buffers, ec);
boost::asio::detail::throw_error(ec, "read_some");
return s;
}
/// Read some data from the pipe.
/**
* This function is used to read data from the pipe. The function call will
* block until one or more bytes of data has been read successfully, or until
* an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes read. Returns 0 if an error occurred.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
boost::system::error_code& ec)
{
return impl_.get_service().read_some(
impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous read.
/**
* This function is used to asynchronously read data from the pipe. The
* function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be read.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read function if you need to ensure that the
* requested amount of data is read before the asynchronous operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* basic_readable_pipe.async_read_some(
* boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) ReadHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_some(const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_read_some(this), handler, buffers);
}
private:
// Disallow copying and assignment.
basic_readable_pipe(const basic_readable_pipe&) BOOST_ASIO_DELETED;
basic_readable_pipe& operator=(const basic_readable_pipe&) BOOST_ASIO_DELETED;
class initiate_async_read_some
{
public:
typedef Executor executor_type;
explicit initiate_async_read_some(basic_readable_pipe* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
const MutableBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self_->impl_.get_service().async_read_some(
self_->impl_.get_implementation(), buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_readable_pipe* self_;
};
#if defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;
#else
detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
#endif
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_PIPE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_BASIC_READABLE_PIPE_HPP

View File

@ -2,7 +2,7 @@
// basic_seq_packet_socket.hpp // basic_seq_packet_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -44,6 +44,12 @@ class basic_seq_packet_socket;
* @par Thread Safety * @par Thread Safety
* @e Distinct @e objects: Safe.@n * @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe. * @e Shared @e objects: Unsafe.
*
* Synchronous @c send, @c receive, 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> template <typename Protocol, typename Executor>
class basic_seq_packet_socket class basic_seq_packet_socket
@ -101,9 +107,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_seq_packet_socket(ExecutionContext& context, explicit basic_seq_packet_socket(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context) : basic_socket<Protocol, Executor>(context)
{ {
} }
@ -144,9 +150,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context, basic_seq_packet_socket(ExecutionContext& context,
const protocol_type& protocol, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
>::type = defaulted_constraint())
: basic_socket<Protocol, Executor>(context, protocol) : basic_socket<Protocol, Executor>(context, protocol)
{ {
} }
@ -191,9 +198,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context, basic_seq_packet_socket(ExecutionContext& context,
const endpoint_type& endpoint, const endpoint_type& endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, endpoint) : basic_socket<Protocol, Executor>(context, endpoint)
{ {
} }
@ -236,9 +243,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext& context, basic_seq_packet_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket, const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket) : basic_socket<Protocol, Executor>(context, protocol, native_socket)
{ {
} }
@ -294,10 +301,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other, basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(std::move(other)) : basic_socket<Protocol, Executor>(std::move(other))
{ {
} }
@ -316,7 +323,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_seq_packet_socket& basic_seq_packet_socket&
@ -428,6 +435,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -601,6 +618,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -660,6 +687,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,

View File

@ -2,7 +2,7 @@
// basic_serial_port.hpp // basic_serial_port.hpp
// ~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
// //
// Distributed under the Boost Software License, Version 1.0. (See accompanying // Distributed under the Boost Software License, Version 1.0. (See accompanying
@ -35,7 +35,7 @@
#if defined(BOOST_ASIO_HAS_IOCP) #if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_serial_port_service.hpp> # include <boost/asio/detail/win_iocp_serial_port_service.hpp>
#else #else
# include <boost/asio/detail/reactive_serial_port_service.hpp> # include <boost/asio/detail/posix_serial_port_service.hpp>
#endif #endif
#if defined(BOOST_ASIO_HAS_MOVE) #if defined(BOOST_ASIO_HAS_MOVE)
@ -79,7 +79,7 @@ public:
typedef detail::win_iocp_serial_port_service::native_handle_type typedef detail::win_iocp_serial_port_service::native_handle_type
native_handle_type; native_handle_type;
#else #else
typedef detail::reactive_serial_port_service::native_handle_type typedef detail::posix_serial_port_service::native_handle_type
native_handle_type; native_handle_type;
#endif #endif
@ -95,7 +95,7 @@ public:
* serial port. * serial port.
*/ */
explicit basic_serial_port(const executor_type& ex) explicit basic_serial_port(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -109,11 +109,11 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_serial_port(ExecutionContext& context, explicit basic_serial_port(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value, is_convertible<ExecutionContext&, execution_context&>::value,
basic_serial_port defaulted_constraint
>::type* = 0) >::type = defaulted_constraint())
: impl_(context) : impl_(0, 0, context)
{ {
} }
@ -130,7 +130,7 @@ public:
* port. * port.
*/ */
basic_serial_port(const executor_type& ex, const char* device) basic_serial_port(const executor_type& ex, const char* device)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec); impl_.get_service().open(impl_.get_implementation(), device, ec);
@ -151,10 +151,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context, const char* device, basic_serial_port(ExecutionContext& context, const char* device,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec); impl_.get_service().open(impl_.get_implementation(), device, ec);
@ -174,7 +174,7 @@ public:
* port. * port.
*/ */
basic_serial_port(const executor_type& ex, const std::string& device) basic_serial_port(const executor_type& ex, const std::string& device)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec); impl_.get_service().open(impl_.get_implementation(), device, ec);
@ -195,10 +195,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context, const std::string& device, basic_serial_port(ExecutionContext& context, const std::string& device,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), device, ec); impl_.get_service().open(impl_.get_implementation(), device, ec);
@ -220,7 +220,7 @@ public:
*/ */
basic_serial_port(const executor_type& ex, basic_serial_port(const executor_type& ex,
const native_handle_type& native_serial_port) const native_handle_type& native_serial_port)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -244,10 +244,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_serial_port(ExecutionContext& context, basic_serial_port(ExecutionContext& context,
const native_handle_type& native_serial_port, const native_handle_type& native_serial_port,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -894,7 +894,7 @@ private:
#if defined(BOOST_ASIO_HAS_IOCP) #if defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_; detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_;
#else #else
detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_; detail::io_object_impl<detail::posix_serial_port_service, Executor> impl_;
#endif #endif
}; };

View File

@ -2,7 +2,7 @@
// basic_signal_set.hpp // basic_signal_set.hpp
// ~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -28,6 +28,8 @@
#include <boost/asio/error.hpp> #include <boost/asio/error.hpp>
#include <boost/asio/execution_context.hpp> #include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost { namespace boost {
namespace asio { namespace asio {
@ -115,7 +117,7 @@ public:
* signal set. * signal set.
*/ */
explicit basic_signal_set(const executor_type& ex) explicit basic_signal_set(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -129,10 +131,11 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_signal_set(ExecutionContext& context, explicit basic_signal_set(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
} }
@ -151,7 +154,7 @@ public:
* signals.add(signal_number_1); @endcode * signals.add(signal_number_1); @endcode
*/ */
basic_signal_set(const executor_type& ex, int signal_number_1) basic_signal_set(const executor_type& ex, int signal_number_1)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -174,10 +177,11 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1, basic_signal_set(ExecutionContext& context, int signal_number_1,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -203,7 +207,7 @@ public:
*/ */
basic_signal_set(const executor_type& ex, int signal_number_1, basic_signal_set(const executor_type& ex, int signal_number_1,
int signal_number_2) int signal_number_2)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -232,10 +236,11 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1, basic_signal_set(ExecutionContext& context, int signal_number_1,
int signal_number_2, int signal_number_2,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -266,7 +271,7 @@ public:
*/ */
basic_signal_set(const executor_type& ex, int signal_number_1, basic_signal_set(const executor_type& ex, int signal_number_1,
int signal_number_2, int signal_number_3) int signal_number_2, int signal_number_3)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -300,10 +305,11 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_signal_set(ExecutionContext& context, int signal_number_1, basic_signal_set(ExecutionContext& context, int signal_number_1,
int signal_number_2, int signal_number_3, int signal_number_2, int signal_number_3,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
@ -567,4 +573,6 @@ private:
} // namespace asio } // namespace asio
} // namespace boost } // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP #endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP

View File

@ -2,7 +2,7 @@
// basic_socket.hpp // basic_socket.hpp
// ~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -32,6 +32,8 @@
# include <boost/asio/detail/null_socket_service.hpp> # include <boost/asio/detail/null_socket_service.hpp>
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_socket_service.hpp> # 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 #else
# include <boost/asio/detail/reactive_socket_service.hpp> # include <boost/asio/detail/reactive_socket_service.hpp>
#endif #endif
@ -88,6 +90,9 @@ public:
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
typedef typename detail::win_iocp_socket_service< typedef typename detail::win_iocp_socket_service<
Protocol>::native_handle_type native_handle_type; 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 #else
typedef typename detail::reactive_socket_service< typedef typename detail::reactive_socket_service<
Protocol>::native_handle_type native_handle_type; Protocol>::native_handle_type native_handle_type;
@ -112,7 +117,7 @@ public:
* dispatch handlers for any asynchronous operations performed on the socket. * dispatch handlers for any asynchronous operations performed on the socket.
*/ */
explicit basic_socket(const executor_type& ex) explicit basic_socket(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -126,10 +131,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_socket(ExecutionContext& context, explicit basic_socket(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
} }
@ -145,7 +150,7 @@ public:
* @throws boost::system::system_error Thrown on failure. * @throws boost::system::system_error Thrown on failure.
*/ */
basic_socket(const executor_type& ex, const protocol_type& protocol) basic_socket(const executor_type& ex, const protocol_type& protocol)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), protocol, ec); impl_.get_service().open(impl_.get_implementation(), protocol, ec);
@ -166,10 +171,11 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket(ExecutionContext& context, const protocol_type& protocol, basic_socket(ExecutionContext& context, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), protocol, ec); impl_.get_service().open(impl_.get_implementation(), protocol, ec);
@ -192,7 +198,7 @@ public:
* @throws boost::system::system_error Thrown on failure. * @throws boost::system::system_error Thrown on failure.
*/ */
basic_socket(const executor_type& ex, const endpoint_type& endpoint) basic_socket(const executor_type& ex, const endpoint_type& endpoint)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol(); const protocol_type protocol = endpoint.protocol();
@ -220,10 +226,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket(ExecutionContext& context, const endpoint_type& endpoint, basic_socket(ExecutionContext& context, const endpoint_type& endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol(); const protocol_type protocol = endpoint.protocol();
@ -248,7 +254,7 @@ public:
*/ */
basic_socket(const executor_type& ex, const protocol_type& protocol, basic_socket(const executor_type& ex, const protocol_type& protocol,
const native_handle_type& native_socket) const native_handle_type& native_socket)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -273,10 +279,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket(ExecutionContext& context, const protocol_type& protocol, basic_socket(ExecutionContext& context, const protocol_type& protocol,
const native_handle_type& native_socket, const native_handle_type& native_socket,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -332,10 +338,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_socket(basic_socket<Protocol1, Executor1>&& other, basic_socket(basic_socket<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: impl_(std::move(other.impl_)) : impl_(std::move(other.impl_))
{ {
} }
@ -351,7 +357,7 @@ public:
* constructed using the @c basic_socket(const executor_type&) constructor. * constructed using the @c basic_socket(const executor_type&) constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_socket& basic_socket&
@ -939,6 +945,16 @@ public:
* boost::asio::ip::address::from_string("1.2.3.4"), 12345); * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_connect(endpoint, connect_handler); * socket.async_connect(endpoint, connect_handler);
* @endcode * @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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 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); * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
* @endcode * @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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
@ -1802,6 +1828,9 @@ protected:
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl< detail::io_object_impl<
detail::win_iocp_socket_service<Protocol>, Executor> 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 #else
detail::io_object_impl< detail::io_object_impl<
detail::reactive_socket_service<Protocol>, Executor> impl_; detail::reactive_socket_service<Protocol>, Executor> impl_;

View File

@ -2,7 +2,7 @@
// basic_socket_acceptor.hpp // basic_socket_acceptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -31,6 +31,8 @@
# include <boost/asio/detail/null_socket_service.hpp> # include <boost/asio/detail/null_socket_service.hpp>
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_socket_service.hpp> # 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 #else
# include <boost/asio/detail/reactive_socket_service.hpp> # include <boost/asio/detail/reactive_socket_service.hpp>
#endif #endif
@ -62,6 +64,12 @@ class basic_socket_acceptor;
* @e Distinct @e objects: Safe.@n * @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe. * @e Shared @e objects: Unsafe.
* *
* Synchronous @c accept operations are thread safe, if the underlying
* operating system calls are also thread safe. This means that it is permitted
* to perform concurrent calls to synchronous @c accept operations on a single
* socket object. Other synchronous operations, such as @c open or @c close, are
* not thread safe.
*
* @par Example * @par Example
* Opening a socket acceptor with the SO_REUSEADDR option enabled: * Opening a socket acceptor with the SO_REUSEADDR option enabled:
* @code * @code
@ -98,6 +106,9 @@ public:
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
typedef typename detail::win_iocp_socket_service< typedef typename detail::win_iocp_socket_service<
Protocol>::native_handle_type native_handle_type; 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 #else
typedef typename detail::reactive_socket_service< typedef typename detail::reactive_socket_service<
Protocol>::native_handle_type native_handle_type; Protocol>::native_handle_type native_handle_type;
@ -120,7 +131,7 @@ public:
* acceptor. * acceptor.
*/ */
explicit basic_socket_acceptor(const executor_type& ex) explicit basic_socket_acceptor(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -136,10 +147,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_socket_acceptor(ExecutionContext& context, explicit basic_socket_acceptor(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
} }
@ -156,7 +167,7 @@ public:
* @throws boost::system::system_error Thrown on failure. * @throws boost::system::system_error Thrown on failure.
*/ */
basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol) basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), protocol, ec); impl_.get_service().open(impl_.get_implementation(), protocol, ec);
@ -178,10 +189,11 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket_acceptor(ExecutionContext& context, basic_socket_acceptor(ExecutionContext& context,
const protocol_type& protocol, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
: impl_(context) >::type = defaulted_constraint())
: impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().open(impl_.get_implementation(), protocol, ec); impl_.get_service().open(impl_.get_implementation(), protocol, ec);
@ -217,7 +229,7 @@ public:
*/ */
basic_socket_acceptor(const executor_type& ex, basic_socket_acceptor(const executor_type& ex,
const endpoint_type& endpoint, bool reuse_addr = true) const endpoint_type& endpoint, bool reuse_addr = true)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol(); const protocol_type protocol = endpoint.protocol();
@ -266,10 +278,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket_acceptor(ExecutionContext& context, basic_socket_acceptor(ExecutionContext& context,
const endpoint_type& endpoint, bool reuse_addr = true, const endpoint_type& endpoint, bool reuse_addr = true,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol(); const protocol_type protocol = endpoint.protocol();
@ -305,7 +317,7 @@ public:
*/ */
basic_socket_acceptor(const executor_type& ex, basic_socket_acceptor(const executor_type& ex,
const protocol_type& protocol, const native_handle_type& native_acceptor) const protocol_type& protocol, const native_handle_type& native_acceptor)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -331,10 +343,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_socket_acceptor(ExecutionContext& context, basic_socket_acceptor(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_acceptor, const protocol_type& protocol, const native_handle_type& native_acceptor,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), impl_.get_service().assign(impl_.get_implementation(),
@ -394,10 +406,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other, basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: impl_(std::move(other.impl_)) : impl_(std::move(other.impl_))
{ {
} }
@ -415,7 +427,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_socket_acceptor& basic_socket_acceptor&
@ -1218,6 +1230,16 @@ public:
* boost::asio::ip::tcp::acceptor::wait_read, * boost::asio::ip::tcp::acceptor::wait_read,
* wait_handler); * wait_handler);
* @endcode * @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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
@ -1253,9 +1275,9 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
void accept(basic_socket<Protocol1, Executor1>& peer, void accept(basic_socket<Protocol1, Executor1>& peer,
typename enable_if< typename constraint<
is_convertible<Protocol, Protocol1>::value is_convertible<Protocol, Protocol1>::value
>::type* = 0) >::type = 0)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().accept(impl_.get_implementation(), impl_.get_service().accept(impl_.get_implementation(),
@ -1289,9 +1311,9 @@ public:
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
BOOST_ASIO_SYNC_OP_VOID accept( BOOST_ASIO_SYNC_OP_VOID accept(
basic_socket<Protocol1, Executor1>& peer, boost::system::error_code& ec, basic_socket<Protocol1, Executor1>& peer, boost::system::error_code& ec,
typename enable_if< typename constraint<
is_convertible<Protocol, Protocol1>::value is_convertible<Protocol, Protocol1>::value
>::type* = 0) >::type = 0)
{ {
impl_.get_service().accept(impl_.get_implementation(), impl_.get_service().accept(impl_.get_implementation(),
peer, static_cast<endpoint_type*>(0), ec); peer, static_cast<endpoint_type*>(0), ec);
@ -1335,6 +1357,16 @@ public:
* boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::socket socket(my_context);
* acceptor.async_accept(socket, accept_handler); * acceptor.async_accept(socket, accept_handler);
* @endcode * @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 <typename Protocol1, typename Executor1, template <typename Protocol1, typename Executor1,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
@ -1344,9 +1376,9 @@ public:
async_accept(basic_socket<Protocol1, Executor1>& peer, async_accept(basic_socket<Protocol1, Executor1>& peer,
BOOST_ASIO_MOVE_ARG(AcceptHandler) handler BOOST_ASIO_MOVE_ARG(AcceptHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),
typename enable_if< typename constraint<
is_convertible<Protocol, Protocol1>::value is_convertible<Protocol, Protocol1>::value
>::type* = 0) >::type = 0)
{ {
return async_initiate<AcceptHandler, void (boost::system::error_code)>( return async_initiate<AcceptHandler, void (boost::system::error_code)>(
initiate_async_accept(this), handler, initiate_async_accept(this), handler,
@ -1448,6 +1480,16 @@ public:
* not, the handler will not be invoked from within this function. On * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * 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 Executor1, template <typename Executor1,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
@ -1570,6 +1612,16 @@ public:
* ... * ...
* acceptor.async_accept(accept_handler); * acceptor.async_accept(accept_handler);
* @endcode * @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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -1619,10 +1671,10 @@ public:
template <typename Executor1> template <typename Executor1>
typename Protocol::socket::template rebind_executor<Executor1>::other typename Protocol::socket::template rebind_executor<Executor1>::other
accept(const Executor1& ex, accept(const Executor1& ex,
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
boost::system::error_code ec; boost::system::error_code ec;
typename Protocol::socket::template typename Protocol::socket::template
@ -1659,9 +1711,9 @@ public:
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other typename ExecutionContext::executor_type>::other
accept(ExecutionContext& context, accept(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
boost::system::error_code ec; boost::system::error_code ec;
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
@ -1702,10 +1754,10 @@ public:
template <typename Executor1> template <typename Executor1>
typename Protocol::socket::template rebind_executor<Executor1>::other typename Protocol::socket::template rebind_executor<Executor1>::other
accept(const Executor1& ex, boost::system::error_code& ec, accept(const Executor1& ex, boost::system::error_code& ec,
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
typename Protocol::socket::template typename Protocol::socket::template
rebind_executor<Executor1>::other peer(ex); rebind_executor<Executor1>::other peer(ex);
@ -1745,9 +1797,9 @@ public:
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other typename ExecutionContext::executor_type>::other
accept(ExecutionContext& context, boost::system::error_code& ec, accept(ExecutionContext& context, boost::system::error_code& ec,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other peer(context); typename ExecutionContext::executor_type>::other peer(context);
@ -1796,6 +1848,16 @@ public:
* ... * ...
* acceptor.async_accept(my_context2, accept_handler); * acceptor.async_accept(my_context2, accept_handler);
* @endcode * @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 <typename Executor1, template <typename Executor1,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -1809,10 +1871,10 @@ public:
async_accept(const Executor1& ex, async_accept(const Executor1& ex,
BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
typedef typename Protocol::socket::template rebind_executor< typedef typename Protocol::socket::template rebind_executor<
Executor1>::other other_socket_type; Executor1>::other other_socket_type;
@ -1866,6 +1928,16 @@ public:
* ... * ...
* acceptor.async_accept(my_context2, accept_handler); * acceptor.async_accept(my_context2, accept_handler);
* @endcode * @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 <typename ExecutionContext, template <typename ExecutionContext,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -1879,9 +1951,9 @@ public:
async_accept(ExecutionContext& context, async_accept(ExecutionContext& context,
BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
typedef typename Protocol::socket::template rebind_executor< typedef typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other other_socket_type; typename ExecutionContext::executor_type>::other other_socket_type;
@ -2014,6 +2086,16 @@ public:
* boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::endpoint endpoint;
* acceptor.async_accept(endpoint, accept_handler); * acceptor.async_accept(endpoint, accept_handler);
* @endcode * @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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -2068,10 +2150,10 @@ public:
template <typename Executor1> template <typename Executor1>
typename Protocol::socket::template rebind_executor<Executor1>::other typename Protocol::socket::template rebind_executor<Executor1>::other
accept(const Executor1& ex, endpoint_type& peer_endpoint, accept(const Executor1& ex, endpoint_type& peer_endpoint,
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
boost::system::error_code ec; boost::system::error_code ec;
typename Protocol::socket::template typename Protocol::socket::template
@ -2114,9 +2196,9 @@ public:
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other typename ExecutionContext::executor_type>::other
accept(ExecutionContext& context, endpoint_type& peer_endpoint, accept(ExecutionContext& context, endpoint_type& peer_endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
boost::system::error_code ec; boost::system::error_code ec;
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
@ -2164,10 +2246,10 @@ public:
typename Protocol::socket::template rebind_executor<Executor1>::other typename Protocol::socket::template rebind_executor<Executor1>::other
accept(const executor_type& ex, accept(const executor_type& ex,
endpoint_type& peer_endpoint, boost::system::error_code& ec, endpoint_type& peer_endpoint, boost::system::error_code& ec,
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
typename Protocol::socket::template typename Protocol::socket::template
rebind_executor<Executor1>::other peer(ex); rebind_executor<Executor1>::other peer(ex);
@ -2214,9 +2296,9 @@ public:
typename ExecutionContext::executor_type>::other typename ExecutionContext::executor_type>::other
accept(ExecutionContext& context, accept(ExecutionContext& context,
endpoint_type& peer_endpoint, boost::system::error_code& ec, endpoint_type& peer_endpoint, boost::system::error_code& ec,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
typename Protocol::socket::template rebind_executor< typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other peer(context); typename ExecutionContext::executor_type>::other peer(context);
@ -2272,6 +2354,16 @@ public:
* boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::endpoint endpoint;
* acceptor.async_accept(my_context2, endpoint, accept_handler); * acceptor.async_accept(my_context2, endpoint, accept_handler);
* @endcode * @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 <typename Executor1, template <typename Executor1,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -2285,10 +2377,10 @@ public:
async_accept(const Executor1& ex, endpoint_type& peer_endpoint, async_accept(const Executor1& ex, endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),
typename enable_if< typename constraint<
is_executor<Executor1>::value is_executor<Executor1>::value
|| execution::is_executor<Executor1>::value || execution::is_executor<Executor1>::value
>::type* = 0) >::type = 0)
{ {
typedef typename Protocol::socket::template rebind_executor< typedef typename Protocol::socket::template rebind_executor<
Executor1>::other other_socket_type; Executor1>::other other_socket_type;
@ -2348,6 +2440,16 @@ public:
* boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::endpoint endpoint;
* acceptor.async_accept(my_context2, endpoint, accept_handler); * acceptor.async_accept(my_context2, endpoint, accept_handler);
* @endcode * @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 <typename ExecutionContext, template <typename ExecutionContext,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -2362,9 +2464,9 @@ public:
endpoint_type& peer_endpoint, endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
{ {
typedef typename Protocol::socket::template rebind_executor< typedef typename Protocol::socket::template rebind_executor<
typename ExecutionContext::executor_type>::other other_socket_type; typename ExecutionContext::executor_type>::other other_socket_type;
@ -2489,6 +2591,9 @@ private:
#elif defined(BOOST_ASIO_HAS_IOCP) #elif defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl< detail::io_object_impl<
detail::win_iocp_socket_service<Protocol>, Executor> 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 #else
detail::io_object_impl< detail::io_object_impl<
detail::reactive_socket_service<Protocol>, Executor> impl_; detail::reactive_socket_service<Protocol>, Executor> impl_;

View File

@ -2,7 +2,7 @@
// basic_socket_iostream.hpp // basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// basic_socket_streambuf.hpp // basic_socket_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -0,0 +1,732 @@
//
// basic_stream_file.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_BASIC_STREAM_FILE_HPP
#define BOOST_ASIO_BASIC_STREAM_FILE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_FILE) \
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_file.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
#if !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
#define BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL
// Forward declaration with defaulted arguments.
template <typename Executor = any_io_executor>
class basic_stream_file;
#endif // !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
/// Provides stream-oriented file functionality.
/**
* The basic_stream_file class template provides asynchronous and blocking
* stream-oriented file functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template <typename Executor>
class basic_stream_file
: public basic_file<Executor>
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the file type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The file type when rebound to the specified executor.
typedef basic_stream_file<Executor1> other;
};
/// The native representation of a file.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#else
typedef typename basic_file<Executor>::native_handle_type native_handle_type;
#endif
/// Construct a basic_stream_file without opening it.
/**
* This constructor initialises a file without opening it. The file needs to
* be opened before data can be read from or or written to it.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*/
explicit basic_stream_file(const executor_type& ex)
: basic_file<Executor>(ex)
{
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
}
/// Construct a basic_stream_file without opening it.
/**
* This constructor initialises a file without opening it. The file needs to
* be opened before data can be read from or or written to it.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*/
template <typename ExecutionContext>
explicit basic_stream_file(ExecutionContext& context,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context)
{
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
}
/// Construct and open a basic_stream_file.
/**
* This constructor initialises and opens a file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_stream_file(const executor_type& ex,
const char* path, file_base::flags open_flags)
: basic_file<Executor>(ex)
{
boost::system::error_code ec;
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
this->impl_.get_service().open(
this->impl_.get_implementation(),
path, open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_stream_file.
/**
* This constructor initialises and opens a file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_file(ExecutionContext& context,
const char* path, file_base::flags open_flags,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context)
{
boost::system::error_code ec;
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
this->impl_.get_service().open(
this->impl_.get_implementation(),
path, open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_stream_file.
/**
* This constructor initialises and opens a file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_stream_file(const executor_type& ex,
const std::string& path, file_base::flags open_flags)
: basic_file<Executor>(ex)
{
boost::system::error_code ec;
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
this->impl_.get_service().open(
this->impl_.get_implementation(),
path.c_str(), open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct and open a basic_stream_file.
/**
* This constructor initialises and opens a file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param path The path name identifying the file to be opened.
*
* @param open_flags A set of flags that determine how the file should be
* opened.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_file(ExecutionContext& context,
const std::string& path, file_base::flags open_flags,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context)
{
boost::system::error_code ec;
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
this->impl_.get_service().open(
this->impl_.get_implementation(),
path.c_str(), open_flags, ec);
boost::asio::detail::throw_error(ec, "open");
}
/// Construct a basic_stream_file on an existing native file.
/**
* This constructor initialises a stream file object to hold an existing
* native file.
*
* @param ex The I/O executor that the file will use, by default, to
* dispatch handlers for any asynchronous operations performed on the file.
*
* @param native_file The new underlying file implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_stream_file(const executor_type& ex,
const native_handle_type& native_file)
: basic_file<Executor>(ex, native_file)
{
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
}
/// Construct a basic_stream_file on an existing native file.
/**
* This constructor initialises a stream file object to hold an existing
* native file.
*
* @param context An execution context which provides the I/O executor that
* the file will use, by default, to dispatch handlers for any asynchronous
* operations performed on the file.
*
* @param native_file The new underlying file implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_stream_file(ExecutionContext& context,
const native_handle_type& native_file,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(context, native_file)
{
this->impl_.get_service().set_is_stream(
this->impl_.get_implementation(), true);
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_stream_file from another.
/**
* This constructor moves a stream file from one object to another.
*
* @param other The other basic_stream_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_file(const executor_type&)
* constructor.
*/
basic_stream_file(basic_stream_file&& other) BOOST_ASIO_NOEXCEPT
: basic_file<Executor>(std::move(other))
{
}
/// Move-assign a basic_stream_file from another.
/**
* This assignment operator moves a stream file from one object to another.
*
* @param other The other basic_stream_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_file(const executor_type&)
* constructor.
*/
basic_stream_file& operator=(basic_stream_file&& other)
{
basic_file<Executor>::operator=(std::move(other));
return *this;
}
/// Move-construct a basic_stream_file from a file of another executor
/// type.
/**
* This constructor moves a stream file from one object to another.
*
* @param other The other basic_stream_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_file(const executor_type&)
* constructor.
*/
template <typename Executor1>
basic_stream_file(basic_stream_file<Executor1>&& other,
typename constraint<
is_convertible<Executor1, Executor>::value,
defaulted_constraint
>::type = defaulted_constraint())
: basic_file<Executor>(std::move(other))
{
}
/// Move-assign a basic_stream_file from a file of another executor type.
/**
* This assignment operator moves a stream file from one object to another.
*
* @param other The other basic_stream_file object from which the move
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_stream_file(const executor_type&)
* constructor.
*/
template <typename Executor1>
typename constraint<
is_convertible<Executor1, Executor>::value,
basic_stream_file&
>::type operator=(basic_stream_file<Executor1>&& other)
{
basic_file<Executor>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroys the file.
/**
* This function destroys the file, cancelling any outstanding asynchronous
* operations associated with the file as if by calling @c cancel.
*/
~basic_stream_file()
{
}
/// Seek to a position in the file.
/**
* This function updates the current position in the file.
*
* @param offset The requested position in the file, relative to @c whence.
*
* @param whence One of @c seek_set, @c seek_cur or @c seek_end.
*
* @returns The new position relative to the beginning of the file.
*
* @throws boost::system::system_error Thrown on failure.
*/
uint64_t seek(int64_t offset, file_base::seek_basis whence)
{
boost::system::error_code ec;
uint64_t n = this->impl_.get_service().seek(
this->impl_.get_implementation(), offset, whence, ec);
boost::asio::detail::throw_error(ec, "seek");
return n;
}
/// Seek to a position in the file.
/**
* This function updates the current position in the file.
*
* @param offset The requested position in the file, relative to @c whence.
*
* @param whence One of @c seek_set, @c seek_cur or @c seek_end.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The new position relative to the beginning of the file.
*/
uint64_t seek(int64_t offset, file_base::seek_basis whence,
boost::system::error_code& ec)
{
return this->impl_.get_service().seek(
this->impl_.get_implementation(), offset, whence, ec);
}
/// Write some data to the file.
/**
* This function is used to write data to the stream file. The function call
* will block until one or more bytes of the data has been written
* successfully, or until an error occurs.
*
* @param buffers One or more data buffers to be written to the file.
*
* @returns The number of bytes written.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the end of the file was reached.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* file.write_some(boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = this->impl_.get_service().write_some(
this->impl_.get_implementation(), buffers, ec);
boost::asio::detail::throw_error(ec, "write_some");
return s;
}
/// Write some data to the file.
/**
* This function is used to write data to the stream file. The function call
* will block until one or more bytes of the data has been written
* successfully, or until an error occurs.
*
* @param buffers One or more data buffers to be written to the file.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes written. Returns 0 if an error occurred.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
boost::system::error_code& ec)
{
return this->impl_.get_service().write_some(
this->impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous write.
/**
* This function is used to asynchronously write data to the stream file.
* The function call always returns immediately.
*
* @param buffers One or more data buffers to be written to the file.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The write operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
* data is written before the asynchronous operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* file.async_write_some(boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on writing 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,
std::size_t)) WriteHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write_some(const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_write_some(this), handler, buffers);
}
/// Read some data from the file.
/**
* This function is used to read data from the stream file. The function
* call will block until one or more bytes of data has been read successfully,
* or until an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @returns The number of bytes read.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the end of the file was reached.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* file.read_some(boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = this->impl_.get_service().read_some(
this->impl_.get_implementation(), buffers, ec);
boost::asio::detail::throw_error(ec, "read_some");
return s;
}
/// Read some data from the file.
/**
* This function is used to read data from the stream file. The function
* call will block until one or more bytes of data has been read successfully,
* or until an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes read. Returns 0 if an error occurred.
*
* @note The read_some operation may not read all of the requested number of
* bytes. Consider using the @ref read function if you need to ensure that
* the requested amount of data is read before the blocking operation
* completes.
*/
template <typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence& buffers,
boost::system::error_code& ec)
{
return this->impl_.get_service().read_some(
this->impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous read.
/**
* This function is used to asynchronously read data from the stream file.
* The function call always returns immediately.
*
* @param buffers One or more buffers into which the data will be read.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the read operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The read operation may not read all of the requested number of bytes.
* Consider using the @ref async_read function if you need to ensure that the
* requested amount of data is read before the asynchronous operation
* completes.
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
* @code
* file.async_read_some(boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on reading 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,
std::size_t)) ReadHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_some(const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<ReadHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_read_some(this), handler, buffers);
}
private:
// Disallow copying and assignment.
basic_stream_file(const basic_stream_file&) BOOST_ASIO_DELETED;
basic_stream_file& operator=(const basic_stream_file&) BOOST_ASIO_DELETED;
class initiate_async_write_some
{
public:
typedef Executor executor_type;
explicit initiate_async_write_some(basic_stream_file* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
const ConstBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self_->impl_.get_service().async_write_some(
self_->impl_.get_implementation(), buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_stream_file* self_;
};
class initiate_async_read_some
{
public:
typedef Executor executor_type;
explicit initiate_async_read_some(basic_stream_file* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename ReadHandler, typename MutableBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
const MutableBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
detail::non_const_lvalue<ReadHandler> handler2(handler);
self_->impl_.get_service().async_read_some(
self_->impl_.get_implementation(), buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_stream_file* self_;
};
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_FILE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_BASIC_STREAM_FILE_HPP

View File

@ -2,7 +2,7 @@
// basic_stream_socket.hpp // basic_stream_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -47,6 +47,12 @@ class basic_stream_socket;
* @e Distinct @e objects: Safe.@n * @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe. * @e Shared @e objects: Unsafe.
* *
* Synchronous @c send, @c receive, 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.
*
* @par Concepts: * @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/ */
@ -106,9 +112,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_stream_socket(ExecutionContext& context, explicit basic_stream_socket(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context) : basic_socket<Protocol, Executor>(context)
{ {
} }
@ -145,9 +151,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context, const protocol_type& protocol, basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value,
>::type* = 0) defaulted_constraint
>::type = defaulted_constraint())
: basic_socket<Protocol, Executor>(context, protocol) : basic_socket<Protocol, Executor>(context, protocol)
{ {
} }
@ -190,9 +197,9 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint, basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, endpoint) : basic_socket<Protocol, Executor>(context, endpoint)
{ {
} }
@ -235,9 +242,9 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
basic_stream_socket(ExecutionContext& context, basic_stream_socket(ExecutionContext& context,
const protocol_type& protocol, const native_handle_type& native_socket, const protocol_type& protocol, const native_handle_type& native_socket,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(context, protocol, native_socket) : basic_socket<Protocol, Executor>(context, protocol, native_socket)
{ {
} }
@ -290,10 +297,10 @@ public:
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other, basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value && is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: basic_socket<Protocol, Executor>(std::move(other)) : basic_socket<Protocol, Executor>(std::move(other))
{ {
} }
@ -310,7 +317,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Protocol1, typename Executor1> template <typename Protocol1, typename Executor1>
typename enable_if< typename constraint<
is_convertible<Protocol1, Protocol>::value is_convertible<Protocol1, Protocol>::value
&& is_convertible<Executor1, Executor>::value, && is_convertible<Executor1, Executor>::value,
basic_stream_socket& basic_stream_socket&
@ -463,6 +470,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -516,6 +533,16 @@ public:
* See the @ref buffer documentation for information on sending multiple * See the @ref buffer documentation for information on sending multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -674,6 +701,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -729,6 +766,16 @@ public:
* See the @ref buffer documentation for information on receiving into * 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 * multiple buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -841,6 +888,16 @@ public:
* See the @ref buffer documentation for information on writing multiple * See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -956,6 +1013,16 @@ public:
* See the @ref buffer documentation for information on reading into multiple * See the @ref buffer documentation for information on reading into multiple
* buffers in one go, and how to use it with arrays, boost::array or * buffers in one go, and how to use it with arrays, boost::array or
* std::vector. * 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, template <typename MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,

View File

@ -2,7 +2,7 @@
// basic_streambuf.hpp // basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// basic_streambuf_fwd.hpp // basic_streambuf_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// basic_waitable_timer.hpp // basic_waitable_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -176,7 +176,7 @@ public:
* dispatch handlers for any asynchronous operations performed on the timer. * dispatch handlers for any asynchronous operations performed on the timer.
*/ */
explicit basic_waitable_timer(const executor_type& ex) explicit basic_waitable_timer(const executor_type& ex)
: impl_(ex) : impl_(0, ex)
{ {
} }
@ -192,10 +192,10 @@ public:
*/ */
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context, explicit basic_waitable_timer(ExecutionContext& context,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
} }
@ -210,7 +210,7 @@ public:
* as an absolute time. * as an absolute time.
*/ */
basic_waitable_timer(const executor_type& ex, const time_point& expiry_time) basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
@ -231,10 +231,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context, explicit basic_waitable_timer(ExecutionContext& context,
const time_point& expiry_time, const time_point& expiry_time,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
@ -252,7 +252,7 @@ public:
* now. * now.
*/ */
basic_waitable_timer(const executor_type& ex, const duration& expiry_time) basic_waitable_timer(const executor_type& ex, const duration& expiry_time)
: impl_(ex) : impl_(0, ex)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_after( impl_.get_service().expires_after(
@ -274,10 +274,10 @@ public:
template <typename ExecutionContext> template <typename ExecutionContext>
explicit basic_waitable_timer(ExecutionContext& context, explicit basic_waitable_timer(ExecutionContext& context,
const duration& expiry_time, const duration& expiry_time,
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0) >::type = 0)
: impl_(context) : impl_(0, 0, context)
{ {
boost::system::error_code ec; boost::system::error_code ec;
impl_.get_service().expires_after( impl_.get_service().expires_after(
@ -338,9 +338,9 @@ public:
template <typename Executor1> template <typename Executor1>
basic_waitable_timer( basic_waitable_timer(
basic_waitable_timer<Clock, WaitTraits, Executor1>&& other, basic_waitable_timer<Clock, WaitTraits, Executor1>&& other,
typename enable_if< typename constraint<
is_convertible<Executor1, Executor>::value is_convertible<Executor1, Executor>::value
>::type* = 0) >::type = 0)
: impl_(std::move(other.impl_)) : impl_(std::move(other.impl_))
{ {
} }
@ -358,7 +358,7 @@ public:
* constructor. * constructor.
*/ */
template <typename Executor1> template <typename Executor1>
typename enable_if< typename constraint<
is_convertible<Executor1, Executor>::value, is_convertible<Executor1, Executor>::value,
basic_waitable_timer& basic_waitable_timer&
>::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other) >::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other)
@ -747,6 +747,16 @@ public:
* not, the handler will not be invoked from within this function. On * not, the handler will not be invoked from within this function. On
* immediate completion, invocation of the handler will be performed in a * immediate completion, invocation of the handler will be performed in a
* manner equivalent to using boost::asio::post(). * manner equivalent to using boost::asio::post().
*
* @par Per-Operation Cancellation
* 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 < template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))

View File

@ -0,0 +1,521 @@
//
// basic_writable_pipe.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_BASIC_WRITABLE_PIPE_HPP
#define BOOST_ASIO_BASIC_WRITABLE_PIPE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_PIPE) \
|| defined(GENERATING_DOCUMENTATION)
#include <string>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/io_object_impl.hpp>
#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/execution_context.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_handle_service.hpp>
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
# include <boost/asio/detail/io_uring_descriptor_service.hpp>
#else
# include <boost/asio/detail/reactive_descriptor_service.hpp>
#endif
#if defined(BOOST_ASIO_HAS_MOVE)
# include <utility>
#endif // defined(BOOST_ASIO_HAS_MOVE)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
/// Provides pipe functionality.
/**
* The basic_writable_pipe class provides a wrapper over pipe
* functionality.
*
* @par Thread Safety
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
template <typename Executor = any_io_executor>
class basic_writable_pipe
{
public:
/// The type of the executor associated with the object.
typedef Executor executor_type;
/// Rebinds the pipe type to another executor.
template <typename Executor1>
struct rebind_executor
{
/// The pipe type when rebound to the specified executor.
typedef basic_writable_pipe<Executor1> other;
};
/// The native representation of a pipe.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
#elif defined(BOOST_ASIO_HAS_IOCP)
typedef detail::win_iocp_handle_service::native_handle_type
native_handle_type;
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
typedef detail::io_uring_descriptor_service::native_handle_type
native_handle_type;
#else
typedef detail::reactive_descriptor_service::native_handle_type
native_handle_type;
#endif
/// A basic_writable_pipe is always the lowest layer.
typedef basic_writable_pipe lowest_layer_type;
/// Construct a basic_writable_pipe without opening it.
/**
* This constructor creates a pipe without opening it.
*
* @param ex The I/O executor that the pipe will use, by default, to dispatch
* handlers for any asynchronous operations performed on the pipe.
*/
explicit basic_writable_pipe(const executor_type& ex)
: impl_(0, ex)
{
}
/// Construct a basic_writable_pipe without opening it.
/**
* This constructor creates a pipe without opening it.
*
* @param context An execution context which provides the I/O executor that
* the pipe will use, by default, to dispatch handlers for any asynchronous
* operations performed on the pipe.
*/
template <typename ExecutionContext>
explicit basic_writable_pipe(ExecutionContext& context,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value,
defaulted_constraint
>::type = defaulted_constraint())
: impl_(0, 0, context)
{
}
/// Construct a basic_writable_pipe on an existing native pipe.
/**
* This constructor creates a pipe object to hold an existing native
* pipe.
*
* @param ex The I/O executor that the pipe will use, by default, to
* dispatch handlers for any asynchronous operations performed on the
* pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
basic_writable_pipe(const executor_type& ex,
const native_handle_type& native_pipe)
: impl_(0, ex)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(),
native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Construct a basic_writable_pipe on an existing native pipe.
/**
* This constructor creates a pipe object to hold an existing native
* pipe.
*
* @param context An execution context which provides the I/O executor that
* the pipe will use, by default, to dispatch handlers for any
* asynchronous operations performed on the pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename ExecutionContext>
basic_writable_pipe(ExecutionContext& context,
const native_handle_type& native_pipe,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type = 0)
: impl_(0, 0, context)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(),
native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a basic_writable_pipe from another.
/**
* This constructor moves a pipe from one object to another.
*
* @param other The other basic_writable_pipe object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_writable_pipe(const executor_type&)
* constructor.
*/
basic_writable_pipe(basic_writable_pipe&& other)
: impl_(std::move(other.impl_))
{
}
/// Move-assign a basic_writable_pipe from another.
/**
* This assignment operator moves a pipe from one object to another.
*
* @param other The other basic_writable_pipe object from which the move will
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
* constructed using the @c basic_writable_pipe(const executor_type&)
* constructor.
*/
basic_writable_pipe& operator=(basic_writable_pipe&& other)
{
impl_ = std::move(other.impl_);
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destroys the pipe.
/**
* This function destroys the pipe, cancelling any outstanding
* asynchronous wait operations associated with the pipe as if by
* calling @c cancel.
*/
~basic_writable_pipe()
{
}
/// Get the executor associated with the object.
executor_type get_executor() BOOST_ASIO_NOEXCEPT
{
return impl_.get_executor();
}
/// Get a reference to the lowest layer.
/**
* This function returns a reference to the lowest layer in a stack of
* layers. Since a basic_writable_pipe cannot contain any further layers, it
* simply returns a reference to itself.
*
* @return A reference to the lowest layer in the stack of layers. Ownership
* is not transferred to the caller.
*/
lowest_layer_type& lowest_layer()
{
return *this;
}
/// Get a const reference to the lowest layer.
/**
* This function returns a const reference to the lowest layer in a stack of
* layers. Since a basic_writable_pipe cannot contain any further layers, it
* simply returns a reference to itself.
*
* @return A const reference to the lowest layer in the stack of layers.
* Ownership is not transferred to the caller.
*/
const lowest_layer_type& lowest_layer() const
{
return *this;
}
/// Assign an existing native pipe to the pipe.
/*
* This function opens the pipe to hold an existing native pipe.
*
* @param native_pipe A native pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
void assign(const native_handle_type& native_pipe)
{
boost::system::error_code ec;
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
boost::asio::detail::throw_error(ec, "assign");
}
/// Assign an existing native pipe to the pipe.
/*
* This function opens the pipe to hold an existing native pipe.
*
* @param native_pipe A native pipe.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,
boost::system::error_code& ec)
{
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the pipe is open.
bool is_open() const
{
return impl_.get_service().is_open(impl_.get_implementation());
}
/// Close the pipe.
/**
* This function is used to close the pipe. Any asynchronous write operations
* will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure.
*/
void close()
{
boost::system::error_code ec;
impl_.get_service().close(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "close");
}
/// Close the pipe.
/**
* This function is used to close the pipe. Any asynchronous write operations
* will be cancelled immediately, and will complete with the
* boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
impl_.get_service().close(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native pipe representation.
/**
* This function may be used to obtain the underlying representation of the
* pipe. This is intended to allow access to native pipe
* functionality that is not otherwise provided.
*/
native_handle_type native_handle()
{
return impl_.get_service().native_handle(impl_.get_implementation());
}
/// Cancel all asynchronous operations associated with the pipe.
/**
* This function causes all outstanding asynchronous write operations to
* finish immediately, and the handlers for cancelled operations will be
* passed the boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure.
*/
void cancel()
{
boost::system::error_code ec;
impl_.get_service().cancel(impl_.get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
}
/// Cancel all asynchronous operations associated with the pipe.
/**
* This function causes all outstanding asynchronous write operations to
* finish immediately, and the handlers for cancelled operations will be
* passed the boost::asio::error::operation_aborted error.
*
* @param ec Set to indicate what error occurred, if any.
*/
BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
impl_.get_service().cancel(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write some data to the pipe.
/**
* This function is used to write data to the pipe. The function call will
* block until one or more bytes of the data has been written successfully,
* or until an error occurs.
*
* @param buffers One or more data buffers to be written to the pipe.
*
* @returns The number of bytes written.
*
* @throws boost::system::system_error Thrown on failure. An error code of
* boost::asio::error::eof indicates that the connection was closed by the
* peer.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* pipe.write_some(boost::asio::buffer(data, size));
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers)
{
boost::system::error_code ec;
std::size_t s = impl_.get_service().write_some(
impl_.get_implementation(), buffers, ec);
boost::asio::detail::throw_error(ec, "write_some");
return s;
}
/// Write some data to the pipe.
/**
* This function is used to write data to the pipe. The function call will
* block until one or more bytes of the data has been written successfully,
* or until an error occurs.
*
* @param buffers One or more data buffers to be written to the pipe.
*
* @param ec Set to indicate what error occurred, if any.
*
* @returns The number of bytes written. Returns 0 if an error occurred.
*
* @note The write_some operation may not transmit all of the data to the
* peer. Consider using the @ref write function if you need to ensure that
* all data is written before the blocking operation completes.
*/
template <typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buffers,
boost::system::error_code& ec)
{
return impl_.get_service().write_some(
impl_.get_implementation(), buffers, ec);
}
/// Start an asynchronous write.
/**
* This function is used to asynchronously write data to the pipe. The
* function call always returns immediately.
*
* @param buffers One or more data buffers to be written to the pipe.
* Although the buffers object may be copied as necessary, ownership of the
* underlying memory blocks is retained by the caller, which must guarantee
* that they remain valid until the handler is called.
*
* @param handler The handler to be called when the write operation completes.
* Copies will be made of the handler as required. The function signature of
* the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
* Regardless of whether the asynchronous operation completes immediately or
* 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().
*
* @note The write operation may not transmit all of the data to the peer.
* Consider using the @ref async_write function if you need to ensure that all
* data is written before the asynchronous operation completes.
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
* @code
* pipe.async_write_some(boost::asio::buffer(data, size), handler);
* @endcode
* See the @ref buffer documentation for information on writing multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
std::size_t)) WriteHandler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write_some(const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
return async_initiate<WriteHandler,
void (boost::system::error_code, std::size_t)>(
initiate_async_write_some(this), handler, buffers);
}
private:
// Disallow copying and assignment.
basic_writable_pipe(const basic_writable_pipe&) BOOST_ASIO_DELETED;
basic_writable_pipe& operator=(const basic_writable_pipe&) BOOST_ASIO_DELETED;
class initiate_async_write_some
{
public:
typedef Executor executor_type;
explicit initiate_async_write_some(basic_writable_pipe* self)
: self_(self)
{
}
executor_type get_executor() const BOOST_ASIO_NOEXCEPT
{
return self_->get_executor();
}
template <typename WriteHandler, typename ConstBufferSequence>
void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
const ConstBufferSequence& buffers) const
{
// If you get an error on the following line it means that your handler
// does not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
detail::non_const_lvalue<WriteHandler> handler2(handler);
self_->impl_.get_service().async_write_some(
self_->impl_.get_implementation(), buffers,
handler2.value, self_->impl_.get_executor());
}
private:
basic_writable_pipe* self_;
};
#if defined(BOOST_ASIO_HAS_IOCP)
detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;
#elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;
#else
detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
#endif
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // defined(BOOST_ASIO_HAS_PIPE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_BASIC_WRITABLE_PIPE_HPP

View File

@ -0,0 +1,723 @@
//
// bind_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_BIND_CANCELLATION_SLOT_HPP
#define BOOST_ASIO_BIND_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/detail/type_traits.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
// Helper to automatically define nested typedef result_type.
template <typename T, typename = void>
struct cancellation_slot_binder_result_type
{
protected:
typedef void result_type_or_void;
};
template <typename T>
struct cancellation_slot_binder_result_type<T,
typename void_type<typename T::result_type>::type>
{
typedef typename T::result_type result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R>
struct cancellation_slot_binder_result_type<R(*)()>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R>
struct cancellation_slot_binder_result_type<R(&)()>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1>
struct cancellation_slot_binder_result_type<R(*)(A1)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1>
struct cancellation_slot_binder_result_type<R(&)(A1)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1, typename A2>
struct cancellation_slot_binder_result_type<R(*)(A1, A2)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
template <typename R, typename A1, typename A2>
struct cancellation_slot_binder_result_type<R(&)(A1, A2)>
{
typedef R result_type;
protected:
typedef result_type result_type_or_void;
};
// Helper to automatically define nested typedef argument_type.
template <typename T, typename = void>
struct cancellation_slot_binder_argument_type {};
template <typename T>
struct cancellation_slot_binder_argument_type<T,
typename void_type<typename T::argument_type>::type>
{
typedef typename T::argument_type argument_type;
};
template <typename R, typename A1>
struct cancellation_slot_binder_argument_type<R(*)(A1)>
{
typedef A1 argument_type;
};
template <typename R, typename A1>
struct cancellation_slot_binder_argument_type<R(&)(A1)>
{
typedef A1 argument_type;
};
// Helper to automatically define nested typedefs first_argument_type and
// second_argument_type.
template <typename T, typename = void>
struct cancellation_slot_binder_argument_types {};
template <typename T>
struct cancellation_slot_binder_argument_types<T,
typename void_type<typename T::first_argument_type>::type>
{
typedef typename T::first_argument_type first_argument_type;
typedef typename T::second_argument_type second_argument_type;
};
template <typename R, typename A1, typename A2>
struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>
{
typedef A1 first_argument_type;
typedef A2 second_argument_type;
};
template <typename R, typename A1, typename A2>
struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>
{
typedef A1 first_argument_type;
typedef A2 second_argument_type;
};
// Helper to enable SFINAE on zero-argument operator() below.
template <typename T, typename = void>
struct cancellation_slot_binder_result_of0
{
typedef void type;
};
template <typename T>
struct cancellation_slot_binder_result_of0<T,
typename void_type<typename result_of<T()>::type>::type>
{
typedef typename result_of<T()>::type type;
};
} // namespace detail
/// A call wrapper type to bind a cancellation slot of type @c CancellationSlot
/// to an object of type @c T.
template <typename T, typename CancellationSlot>
class cancellation_slot_binder
#if !defined(GENERATING_DOCUMENTATION)
: public detail::cancellation_slot_binder_result_type<T>,
public detail::cancellation_slot_binder_argument_type<T>,
public detail::cancellation_slot_binder_argument_types<T>
#endif // !defined(GENERATING_DOCUMENTATION)
{
public:
/// The type of the target object.
typedef T target_type;
/// The type of the associated cancellation slot.
typedef CancellationSlot cancellation_slot_type;
#if defined(GENERATING_DOCUMENTATION)
/// The return type if a function.
/**
* The type of @c result_type is based on the type @c T of the wrapper's
* target object:
*
* @li if @c T is a pointer to function type, @c result_type is a synonym for
* the return type of @c T;
*
* @li if @c T is a class type with a member type @c result_type, then @c
* result_type is a synonym for @c T::result_type;
*
* @li otherwise @c result_type is not defined.
*/
typedef see_below result_type;
/// The type of the function's argument.
/**
* The type of @c argument_type is based on the type @c T of the wrapper's
* target object:
*
* @li if @c T is a pointer to a function type accepting a single argument,
* @c argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c argument_type, then @c
* argument_type is a synonym for @c T::argument_type;
*
* @li otherwise @c argument_type is not defined.
*/
typedef see_below argument_type;
/// The type of the function's first argument.
/**
* The type of @c first_argument_type is based on the type @c T of the
* wrapper's target object:
*
* @li if @c T is a pointer to a function type accepting two arguments, @c
* first_argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c first_argument_type,
* then @c first_argument_type is a synonym for @c T::first_argument_type;
*
* @li otherwise @c first_argument_type is not defined.
*/
typedef see_below first_argument_type;
/// The type of the function's second argument.
/**
* The type of @c second_argument_type is based on the type @c T of the
* wrapper's target object:
*
* @li if @c T is a pointer to a function type accepting two arguments, @c
* second_argument_type is a synonym for the return type of @c T;
*
* @li if @c T is a class type with a member type @c first_argument_type,
* then @c second_argument_type is a synonym for @c T::second_argument_type;
*
* @li otherwise @c second_argument_type is not defined.
*/
typedef see_below second_argument_type;
#endif // defined(GENERATING_DOCUMENTATION)
/// Construct a cancellation slot wrapper for the specified object.
/**
* This constructor is only valid if the type @c T is constructible from type
* @c U.
*/
template <typename U>
cancellation_slot_binder(const cancellation_slot_type& s,
BOOST_ASIO_MOVE_ARG(U) u)
: slot_(s),
target_(BOOST_ASIO_MOVE_CAST(U)(u))
{
}
/// Copy constructor.
cancellation_slot_binder(const cancellation_slot_binder& other)
: slot_(other.get_cancellation_slot()),
target_(other.get())
{
}
/// Construct a copy, but specify a different cancellation slot.
cancellation_slot_binder(const cancellation_slot_type& s,
const cancellation_slot_binder& other)
: slot_(s),
target_(other.get())
{
}
/// Construct a copy of a different cancellation slot wrapper type.
/**
* This constructor is only valid if the @c CancellationSlot type is
* constructible from type @c OtherCancellationSlot, and the type @c T is
* constructible from type @c U.
*/
template <typename U, typename OtherCancellationSlot>
cancellation_slot_binder(
const cancellation_slot_binder<U, OtherCancellationSlot>& other)
: slot_(other.get_cancellation_slot()),
target_(other.get())
{
}
/// Construct a copy of a different cancellation slot wrapper type, but
/// specify a different cancellation slot.
/**
* This constructor is only valid if the type @c T is constructible from type
* @c U.
*/
template <typename U, typename OtherCancellationSlot>
cancellation_slot_binder(const cancellation_slot_type& s,
const cancellation_slot_binder<U, OtherCancellationSlot>& other)
: slot_(s),
target_(other.get())
{
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move constructor.
cancellation_slot_binder(cancellation_slot_binder&& other)
: slot_(BOOST_ASIO_MOVE_CAST(cancellation_slot_type)(
other.get_cancellation_slot())),
target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
{
}
/// Move construct the target object, but specify a different cancellation
/// slot.
cancellation_slot_binder(const cancellation_slot_type& s,
cancellation_slot_binder&& other)
: slot_(s),
target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
{
}
/// Move construct from a different cancellation slot wrapper type.
template <typename U, typename OtherCancellationSlot>
cancellation_slot_binder(
cancellation_slot_binder<U, OtherCancellationSlot>&& other)
: slot_(BOOST_ASIO_MOVE_CAST(OtherCancellationSlot)(
other.get_cancellation_slot())),
target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
{
}
/// Move construct from a different cancellation slot wrapper type, but
/// specify a different cancellation slot.
template <typename U, typename OtherCancellationSlot>
cancellation_slot_binder(const cancellation_slot_type& s,
cancellation_slot_binder<U, OtherCancellationSlot>&& other)
: slot_(s),
target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destructor.
~cancellation_slot_binder()
{
}
/// Obtain a reference to the target object.
target_type& get() BOOST_ASIO_NOEXCEPT
{
return target_;
}
/// Obtain a reference to the target object.
const target_type& get() const BOOST_ASIO_NOEXCEPT
{
return target_;
}
/// Obtain the associated cancellation slot.
cancellation_slot_type get_cancellation_slot() const BOOST_ASIO_NOEXCEPT
{
return slot_;
}
#if defined(GENERATING_DOCUMENTATION)
template <typename... Args> auto operator()(Args&& ...);
template <typename... Args> auto operator()(Args&& ...) const;
#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
/// Forwarding function call operator.
template <typename... Args>
typename result_of<T(Args...)>::type operator()(
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
/// Forwarding function call operator.
template <typename... Args>
typename result_of<T(Args...)>::type operator()(
BOOST_ASIO_MOVE_ARG(Args)... args) const
{
return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#elif defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
typename detail::cancellation_slot_binder_result_of0<T>::type operator()()
{
return target_();
}
typename detail::cancellation_slot_binder_result_of0<T>::type
operator()() const
{
return target_();
}
#define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
#undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
#else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
typedef typename detail::cancellation_slot_binder_result_type<
T>::result_type_or_void result_type_or_void;
result_type_or_void operator()()
{
return target_();
}
result_type_or_void operator()() const
{
return target_();
}
#define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
result_type_or_void operator()( \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
result_type_or_void operator()( \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
#undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
#endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
private:
CancellationSlot slot_;
T target_;
};
/// Associate an object of type @c T with a cancellation slot of type
/// @c CancellationSlot.
template <typename CancellationSlot, typename T>
inline cancellation_slot_binder<typename decay<T>::type, CancellationSlot>
bind_cancellation_slot(const CancellationSlot& s, BOOST_ASIO_MOVE_ARG(T) t)
{
return cancellation_slot_binder<
typename decay<T>::type, CancellationSlot>(
s, BOOST_ASIO_MOVE_CAST(T)(t));
}
#if !defined(GENERATING_DOCUMENTATION)
namespace detail {
template <typename TargetAsyncResult,
typename CancellationSlot, typename = void>
struct cancellation_slot_binder_async_result_completion_handler_type
{
};
template <typename TargetAsyncResult, typename CancellationSlot>
struct cancellation_slot_binder_async_result_completion_handler_type<
TargetAsyncResult, CancellationSlot,
typename void_type<
typename TargetAsyncResult::completion_handler_type
>::type>
{
typedef cancellation_slot_binder<
typename TargetAsyncResult::completion_handler_type, CancellationSlot>
completion_handler_type;
};
template <typename TargetAsyncResult, typename = void>
struct cancellation_slot_binder_async_result_return_type
{
};
template <typename TargetAsyncResult>
struct cancellation_slot_binder_async_result_return_type<
TargetAsyncResult,
typename void_type<
typename TargetAsyncResult::return_type
>::type>
{
typedef typename TargetAsyncResult::return_type return_type;
};
} // namespace detail
template <typename T, typename CancellationSlot, typename Signature>
class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :
public detail::cancellation_slot_binder_async_result_completion_handler_type<
async_result<T, Signature>, CancellationSlot>,
public detail::cancellation_slot_binder_async_result_return_type<
async_result<T, Signature> >
{
public:
explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)
: target_(b.get())
{
}
typename async_result<T, Signature>::return_type get()
{
return target_.get();
}
template <typename Initiation>
struct init_wrapper
{
template <typename Init>
init_wrapper(const CancellationSlot& slot, BOOST_ASIO_MOVE_ARG(Init) init)
: slot_(slot),
initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
{
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
cancellation_slot_binder<
typename decay<Handler>::type, CancellationSlot>(
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args) const
{
initiation_(
cancellation_slot_binder<
typename decay<Handler>::type, CancellationSlot>(
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
cancellation_slot_binder<
typename decay<Handler>::type, CancellationSlot>(
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
}
template <typename Handler>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler) const
{
initiation_(
cancellation_slot_binder<
typename decay<Handler>::type, CancellationSlot>(
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
}
#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()( \
BOOST_ASIO_MOVE_ARG(Handler) handler, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
cancellation_slot_binder< \
typename decay<Handler>::type, CancellationSlot>( \
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()( \
BOOST_ASIO_MOVE_ARG(Handler) handler, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
initiation_( \
cancellation_slot_binder< \
typename decay<Handler>::type, CancellationSlot>( \
slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
#undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
CancellationSlot slot_;
Initiation initiation_;
};
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
(async_result<T, Signature>::initiate(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<T>(), declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<T, Signature>(
init_wrapper<typename decay<Initiation>::type>(
token.get_cancellation_slot(),
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.get(), BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
(async_result<T, Signature>::initiate(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<T>())))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
{
return async_initiate<T, Signature>(
init_wrapper<typename decay<Initiation>::type>(
token.get_cancellation_slot(),
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.get());
}
#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename Initiation, typename RawCompletionToken, \
BOOST_ASIO_VARIADIC_TPARAMS(n)> \
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
(async_result<T, Signature>::initiate( \
declval<init_wrapper<typename decay<Initiation>::type> >(), \
declval<T>(), BOOST_ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
initiate( \
BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_initiate<T, Signature>( \
init_wrapper<typename decay<Initiation>::type>( \
token.get_cancellation_slot(), \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
token.get(), BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
#undef BOOST_ASIO_PRIVATE_INITIATE_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
private:
async_result(const async_result&) BOOST_ASIO_DELETED;
async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
async_result<T, Signature> target_;
};
template <template <typename, typename> class Associator,
typename T, typename CancellationSlot, typename DefaultCandidate>
struct associator<Associator,
cancellation_slot_binder<T, CancellationSlot>,
DefaultCandidate>
{
typedef typename Associator<T, DefaultCandidate>::type type;
static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
{
return Associator<T, DefaultCandidate>::get(b.get(), c);
}
};
template <typename T, typename CancellationSlot, typename CancellationSlot1>
struct associated_cancellation_slot<
cancellation_slot_binder<T, CancellationSlot>,
CancellationSlot1>
{
typedef CancellationSlot type;
static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
const CancellationSlot1& = CancellationSlot1()) BOOST_ASIO_NOEXCEPT
{
return b.get_cancellation_slot();
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_BIND_CANCELLATION_SLOT_HPP

View File

@ -2,7 +2,7 @@
// bind_executor.hpp // bind_executor.hpp
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -19,7 +19,7 @@
#include <boost/asio/detail/type_traits.hpp> #include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/variadic_templates.hpp> #include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/associated_executor.hpp> #include <boost/asio/associated_executor.hpp>
#include <boost/asio/associated_allocator.hpp> #include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp> #include <boost/asio/async_result.hpp>
#include <boost/asio/execution/executor.hpp> #include <boost/asio/execution/executor.hpp>
#include <boost/asio/execution_context.hpp> #include <boost/asio/execution_context.hpp>
@ -489,9 +489,9 @@ private:
template <typename Executor, typename T> template <typename Executor, typename T>
inline executor_binder<typename decay<T>::type, Executor> inline executor_binder<typename decay<T>::type, Executor>
bind_executor(const Executor& ex, BOOST_ASIO_MOVE_ARG(T) t, bind_executor(const Executor& ex, BOOST_ASIO_MOVE_ARG(T) t,
typename enable_if< typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type* = 0) >::type = 0)
{ {
return executor_binder<typename decay<T>::type, Executor>( return executor_binder<typename decay<T>::type, Executor>(
executor_arg_t(), ex, BOOST_ASIO_MOVE_CAST(T)(t)); executor_arg_t(), ex, BOOST_ASIO_MOVE_CAST(T)(t));
@ -502,8 +502,8 @@ template <typename ExecutionContext, typename T>
inline executor_binder<typename decay<T>::type, inline executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type> typename ExecutionContext::executor_type>
bind_executor(ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(T) t, bind_executor(ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(T) t,
typename enable_if<is_convertible< typename constraint<is_convertible<
ExecutionContext&, execution_context&>::value>::type* = 0) ExecutionContext&, execution_context&>::value>::type = 0)
{ {
return executor_binder<typename decay<T>::type, return executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type>( typename ExecutionContext::executor_type>(
@ -516,42 +516,235 @@ template <typename T, typename Executor>
struct uses_executor<executor_binder<T, Executor>, Executor> struct uses_executor<executor_binder<T, Executor>, Executor>
: true_type {}; : true_type {};
template <typename T, typename Executor, typename Signature> namespace detail {
class async_result<executor_binder<T, Executor>, Signature>
template <typename TargetAsyncResult, typename Executor, typename = void>
class executor_binder_completion_handler_async_result
{
public:
template <typename T>
explicit executor_binder_completion_handler_async_result(T&)
{
}
};
template <typename TargetAsyncResult, typename Executor>
class executor_binder_completion_handler_async_result<
TargetAsyncResult, Executor,
typename void_type<
typename TargetAsyncResult::completion_handler_type
>::type>
{ {
public: public:
typedef executor_binder< typedef executor_binder<
typename async_result<T, Signature>::completion_handler_type, Executor> typename TargetAsyncResult::completion_handler_type, Executor>
completion_handler_type; completion_handler_type;
typedef typename async_result<T, Signature>::return_type return_type; explicit executor_binder_completion_handler_async_result(
typename TargetAsyncResult::completion_handler_type& handler)
explicit async_result(executor_binder<T, Executor>& b) : target_(handler)
: target_(b.get())
{ {
} }
return_type get() typename TargetAsyncResult::return_type get()
{ {
return target_.get(); return target_.get();
} }
private: private:
async_result(const async_result&) BOOST_ASIO_DELETED; TargetAsyncResult target_;
async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
async_result<T, Signature> target_;
}; };
template <typename T, typename Executor, typename Allocator> template <typename TargetAsyncResult, typename = void>
struct associated_allocator<executor_binder<T, Executor>, Allocator> struct executor_binder_async_result_return_type
{ {
typedef typename associated_allocator<T, Allocator>::type type; };
template <typename TargetAsyncResult>
struct executor_binder_async_result_return_type<
TargetAsyncResult,
typename void_type<
typename TargetAsyncResult::return_type
>::type>
{
typedef typename TargetAsyncResult::return_type return_type;
};
} // namespace detail
template <typename T, typename Executor, typename Signature>
class async_result<executor_binder<T, Executor>, Signature> :
public detail::executor_binder_completion_handler_async_result<
async_result<T, Signature>, Executor>,
public detail::executor_binder_async_result_return_type<
async_result<T, Signature> >
{
public:
explicit async_result(executor_binder<T, Executor>& b)
: detail::executor_binder_completion_handler_async_result<
async_result<T, Signature>, Executor>(b.get())
{
}
template <typename Initiation>
struct init_wrapper
{
template <typename Init>
init_wrapper(const Executor& ex, BOOST_ASIO_MOVE_ARG(Init) init)
: ex_(ex),
initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
{
}
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
executor_binder<typename decay<Handler>::type, Executor>(
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
template <typename Handler, typename... Args>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Args)... args) const
{
initiation_(
executor_binder<typename decay<Handler>::type, Executor>(
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Handler>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler)
{
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
executor_binder<typename decay<Handler>::type, Executor>(
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
}
template <typename Handler>
void operator()(
BOOST_ASIO_MOVE_ARG(Handler) handler) const
{
initiation_(
executor_binder<typename decay<Handler>::type, Executor>(
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
}
#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()( \
BOOST_ASIO_MOVE_ARG(Handler) handler, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
executor_binder<typename decay<Handler>::type, Executor>( \
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
\
template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
void operator()( \
BOOST_ASIO_MOVE_ARG(Handler) handler, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
{ \
initiation_( \
executor_binder<typename decay<Handler>::type, Executor>( \
executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
#undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Executor ex_;
Initiation initiation_;
};
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken, typename... Args>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
(async_result<T, Signature>::initiate(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<T>(), declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
BOOST_ASIO_MOVE_ARG(Args)... args)
{
return async_initiate<T, Signature>(
init_wrapper<typename decay<Initiation>::type>(
token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.get(), BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Initiation, typename RawCompletionToken>
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
(async_result<T, Signature>::initiate(
declval<init_wrapper<typename decay<Initiation>::type> >(),
declval<T>())))
initiate(
BOOST_ASIO_MOVE_ARG(Initiation) initiation,
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
{
return async_initiate<T, Signature>(
init_wrapper<typename decay<Initiation>::type>(
token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
token.get());
}
#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
template <typename Initiation, typename RawCompletionToken, \
BOOST_ASIO_VARIADIC_TPARAMS(n)> \
static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
(async_result<T, Signature>::initiate( \
declval<init_wrapper<typename decay<Initiation>::type> >(), \
declval<T>(), BOOST_ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
initiate( \
BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
return async_initiate<T, Signature>( \
init_wrapper<typename decay<Initiation>::type>( \
token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
token.get(), BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
#undef BOOST_ASIO_PRIVATE_INITIATE_DEF
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
private:
async_result(const async_result&) BOOST_ASIO_DELETED;
async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
};
template <template <typename, typename> class Associator,
typename T, typename Executor, typename DefaultCandidate>
struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>
{
typedef typename Associator<T, DefaultCandidate>::type type;
static type get(const executor_binder<T, Executor>& b, static type get(const executor_binder<T, Executor>& b,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
{ {
return associated_allocator<T, Allocator>::get(b.get(), a); return Associator<T, DefaultCandidate>::get(b.get(), c);
} }
}; };

View File

@ -2,7 +2,7 @@
// buffer.hpp // buffer.hpp
// ~~~~~~~~~~ // ~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -387,9 +387,9 @@ private:
/// Get an iterator to the first element in a buffer sequence. /// Get an iterator to the first element in a buffer sequence.
template <typename MutableBuffer> template <typename MutableBuffer>
inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b, inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
typename enable_if< typename constraint<
is_convertible<const MutableBuffer*, const mutable_buffer*>::value 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)); return static_cast<const mutable_buffer*>(detail::addressof(b));
} }
@ -397,9 +397,9 @@ inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
/// Get an iterator to the first element in a buffer sequence. /// Get an iterator to the first element in a buffer sequence.
template <typename ConstBuffer> template <typename ConstBuffer>
inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b, inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
typename enable_if< typename constraint<
is_convertible<const ConstBuffer*, const const_buffer*>::value 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)); return static_cast<const const_buffer*>(detail::addressof(b));
} }
@ -409,10 +409,10 @@ inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
/// Get an iterator to the first element in a buffer sequence. /// Get an iterator to the first element in a buffer sequence.
template <typename C> template <typename C>
inline auto buffer_sequence_begin(C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_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(); return c.begin();
} }
@ -420,10 +420,10 @@ inline auto buffer_sequence_begin(C& c,
/// Get an iterator to the first element in a buffer sequence. /// Get an iterator to the first element in a buffer sequence.
template <typename C> template <typename C>
inline auto buffer_sequence_begin(const C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_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(); return c.begin();
} }
@ -432,20 +432,20 @@ inline auto buffer_sequence_begin(const C& c,
template <typename C> template <typename C>
inline typename C::iterator buffer_sequence_begin(C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return c.begin(); return c.begin();
} }
template <typename C> template <typename C>
inline typename C::const_iterator buffer_sequence_begin(const C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return c.begin(); return c.begin();
} }
@ -464,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. /// Get an iterator to one past the end element in a buffer sequence.
template <typename MutableBuffer> template <typename MutableBuffer>
inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b, inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
typename enable_if< typename constraint<
is_convertible<const MutableBuffer*, const mutable_buffer*>::value 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; return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
} }
@ -474,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. /// Get an iterator to one past the end element in a buffer sequence.
template <typename ConstBuffer> template <typename ConstBuffer>
inline const const_buffer* buffer_sequence_end(const ConstBuffer& b, inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
typename enable_if< typename constraint<
is_convertible<const ConstBuffer*, const const_buffer*>::value 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; return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
} }
@ -486,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. /// Get an iterator to one past the end element in a buffer sequence.
template <typename C> template <typename C>
inline auto buffer_sequence_end(C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_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(); return c.end();
} }
@ -497,10 +497,10 @@ inline auto buffer_sequence_end(C& c,
/// Get an iterator to one past the end element in a buffer sequence. /// Get an iterator to one past the end element in a buffer sequence.
template <typename C> template <typename C>
inline auto buffer_sequence_end(const C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_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(); return c.end();
} }
@ -509,20 +509,20 @@ inline auto buffer_sequence_end(const C& c,
template <typename C> template <typename C>
inline typename C::iterator buffer_sequence_end(C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return c.end(); return c.end();
} }
template <typename C> template <typename C>
inline typename C::const_iterator buffer_sequence_end(const C& 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 mutable_buffer*>::value
&& !is_convertible<const C*, const const_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
{ {
return c.end(); return c.end();
} }

View File

@ -0,0 +1,330 @@
//
// buffer_registration.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_BUFFER_REGISTRATION_HPP
#define BOOST_ASIO_BUFFER_REGISTRATION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <iterator>
#include <vector>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/execution/context.hpp>
#include <boost/asio/execution/executor.hpp>
#include <boost/asio/execution_context.hpp>
#include <boost/asio/is_executor.hpp>
#include <boost/asio/query.hpp>
#include <boost/asio/registered_buffer.hpp>
#if defined(BOOST_ASIO_HAS_IO_URING)
# include <boost/asio/detail/scheduler.hpp>
# include <boost/asio/detail/io_uring_service.hpp>
#endif // defined(BOOST_ASIO_HAS_IO_URING)
#if defined(BOOST_ASIO_HAS_MOVE)
# include <utility>
#endif // defined(BOOST_ASIO_HAS_MOVE)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
class buffer_registration_base
{
protected:
static mutable_registered_buffer make_buffer(const mutable_buffer& b,
const void* scope, int index) BOOST_ASIO_NOEXCEPT
{
return mutable_registered_buffer(b, registered_buffer_id(scope, index));
}
};
} // namespace detail
/// Automatically registers and unregistered buffers with an execution context.
/**
* For portability, applications should assume that only one registration is
* permitted per execution context.
*/
template <typename MutableBufferSequence,
typename Allocator = std::allocator<void> >
class buffer_registration
: detail::buffer_registration_base
{
public:
/// The allocator type used for allocating storage for the buffers container.
typedef Allocator allocator_type;
#if defined(GENERATING_DOCUMENTATION)
/// The type of an iterator over the registered buffers.
typedef unspecified iterator;
/// The type of a const iterator over the registered buffers.
typedef unspecified const_iterator;
#else // defined(GENERATING_DOCUMENTATION)
typedef std::vector<mutable_registered_buffer>::const_iterator iterator;
typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator;
#endif // defined(GENERATING_DOCUMENTATION)
/// Register buffers with an executor's execution context.
template <typename Executor>
buffer_registration(const Executor& ex,
const MutableBufferSequence& buffer_sequence,
const allocator_type& alloc = allocator_type(),
typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type = 0)
: buffer_sequence_(buffer_sequence),
buffers_(
BOOST_ASIO_REBIND_ALLOC(allocator_type,
mutable_registered_buffer)(alloc))
{
init_buffers(buffer_registration::get_context(ex),
boost::asio::buffer_sequence_begin(buffer_sequence_),
boost::asio::buffer_sequence_end(buffer_sequence_));
}
/// Register buffers with an execution context.
template <typename ExecutionContext>
buffer_registration(ExecutionContext& ctx,
const MutableBufferSequence& buffer_sequence,
const allocator_type& alloc = allocator_type(),
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type = 0)
: buffer_sequence_(buffer_sequence),
buffers_(
BOOST_ASIO_REBIND_ALLOC(allocator_type,
mutable_registered_buffer)(alloc))
{
init_buffers(ctx,
boost::asio::buffer_sequence_begin(buffer_sequence_),
boost::asio::buffer_sequence_end(buffer_sequence_));
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move constructor.
buffer_registration(buffer_registration&& other) BOOST_ASIO_NOEXCEPT
: buffer_sequence_(std::move(other.buffer_sequence_)),
buffers_(std::move(other.buffers_))
{
#if defined(BOOST_ASIO_HAS_IO_URING)
service_ = other.service_;
other.service_ = 0;
#endif // defined(BOOST_ASIO_HAS_IO_URING)
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Unregisters the buffers.
~buffer_registration()
{
#if defined(BOOST_ASIO_HAS_IO_URING)
if (service_)
service_->unregister_buffers();
#endif // defined(BOOST_ASIO_HAS_IO_URING)
}
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move assignment.
buffer_registration& operator=(
buffer_registration&& other) BOOST_ASIO_NOEXCEPT
{
if (this != &other)
{
buffer_sequence_ = std::move(other.buffer_sequence_);
buffers_ = std::move(other.buffers_);
#if defined(BOOST_ASIO_HAS_IO_URING)
if (service_)
service_->unregister_buffers();
service_ = other.service_;
other.service_ = 0;
#endif // defined(BOOST_ASIO_HAS_IO_URING)
}
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Get the number of registered buffers.
std::size_t size() const BOOST_ASIO_NOEXCEPT
{
return buffers_.size();
}
/// Get the begin iterator for the sequence of registered buffers.
const_iterator begin() const BOOST_ASIO_NOEXCEPT
{
return buffers_.begin();
}
/// Get the begin iterator for the sequence of registered buffers.
const_iterator cbegin() const BOOST_ASIO_NOEXCEPT
{
return buffers_.cbegin();
}
/// Get the end iterator for the sequence of registered buffers.
const_iterator end() const BOOST_ASIO_NOEXCEPT
{
return buffers_.end();
}
/// Get the end iterator for the sequence of registered buffers.
const_iterator cend() const BOOST_ASIO_NOEXCEPT
{
return buffers_.cend();
}
/// Get the buffer at the specified index.
const mutable_registered_buffer& operator[](std::size_t i) BOOST_ASIO_NOEXCEPT
{
return buffers_[i];
}
/// Get the buffer at the specified index.
const mutable_registered_buffer& at(std::size_t i) BOOST_ASIO_NOEXCEPT
{
return buffers_.at(i);
}
private:
// Disallow copying and assignment.
buffer_registration(const buffer_registration&) BOOST_ASIO_DELETED;
buffer_registration& operator=(const buffer_registration&) BOOST_ASIO_DELETED;
// Helper function to get an executor's context.
template <typename T>
static execution_context& get_context(const T& t,
typename enable_if<execution::is_executor<T>::value>::type* = 0)
{
return boost::asio::query(t, execution::context);
}
// Helper function to get an executor's context.
template <typename T>
static execution_context& get_context(const T& t,
typename enable_if<!execution::is_executor<T>::value>::type* = 0)
{
return t.context();
}
// Helper function to initialise the container of buffers.
template <typename Iterator>
void init_buffers(execution_context& ctx, Iterator begin, Iterator end)
{
std::size_t n = std::distance(begin, end);
buffers_.resize(n);
#if defined(BOOST_ASIO_HAS_IO_URING)
service_ = &use_service<detail::io_uring_service>(ctx);
std::vector<iovec,
BOOST_ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n,
BOOST_ASIO_REBIND_ALLOC(allocator_type, iovec)(
buffers_.get_allocator()));
#endif // defined(BOOST_ASIO_HAS_IO_URING)
Iterator iter = begin;
for (int index = 0; iter != end; ++index, ++iter)
{
mutable_buffer b(*iter);
std::size_t i = static_cast<std::size_t>(index);
buffers_[i] = this->make_buffer(b, &ctx, index);
#if defined(BOOST_ASIO_HAS_IO_URING)
iovecs[i].iov_base = buffers_[i].data();
iovecs[i].iov_len = buffers_[i].size();
#endif // defined(BOOST_ASIO_HAS_IO_URING)
}
#if defined(BOOST_ASIO_HAS_IO_URING)
if (n > 0)
{
service_->register_buffers(&iovecs[0],
static_cast<unsigned>(iovecs.size()));
}
#endif // defined(BOOST_ASIO_HAS_IO_URING)
}
MutableBufferSequence buffer_sequence_;
std::vector<mutable_registered_buffer,
BOOST_ASIO_REBIND_ALLOC(allocator_type,
mutable_registered_buffer)> buffers_;
#if defined(BOOST_ASIO_HAS_IO_URING)
detail::io_uring_service* service_;
#endif // defined(BOOST_ASIO_HAS_IO_URING)
};
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Register buffers with an execution context.
template <typename Executor, typename MutableBufferSequence>
BOOST_ASIO_NODISCARD inline
buffer_registration<MutableBufferSequence>
register_buffers(const Executor& ex,
const MutableBufferSequence& buffer_sequence,
typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type = 0)
{
return buffer_registration<MutableBufferSequence>(ex, buffer_sequence);
}
/// Register buffers with an execution context.
template <typename Executor, typename MutableBufferSequence, typename Allocator>
BOOST_ASIO_NODISCARD inline
buffer_registration<MutableBufferSequence, Allocator>
register_buffers(const Executor& ex,
const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type = 0)
{
return buffer_registration<MutableBufferSequence, Allocator>(
ex, buffer_sequence, alloc);
}
/// Register buffers with an execution context.
template <typename ExecutionContext, typename MutableBufferSequence>
BOOST_ASIO_NODISCARD inline
buffer_registration<MutableBufferSequence>
register_buffers(ExecutionContext& ctx,
const MutableBufferSequence& buffer_sequence,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type = 0)
{
return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence);
}
/// Register buffers with an execution context.
template <typename ExecutionContext,
typename MutableBufferSequence, typename Allocator>
BOOST_ASIO_NODISCARD inline
buffer_registration<MutableBufferSequence, Allocator>
register_buffers(ExecutionContext& ctx,
const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value
>::type = 0)
{
return buffer_registration<MutableBufferSequence, Allocator>(
ctx, buffer_sequence, alloc);
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_BUFFER_REGISTRATION_HPP

View File

@ -2,7 +2,7 @@
// buffered_read_stream.hpp // buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffered_read_stream_fwd.hpp // buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffered_stream.hpp // buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffered_stream_fwd.hpp // buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffered_write_stream.hpp // buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffered_write_stream_fwd.hpp // buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// buffers_iterator.hpp // buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

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,237 @@
//
// cancellation_state.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_STATE_HPP
#define BOOST_ASIO_CANCELLATION_STATE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <cassert>
#include <new>
#include <utility>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/detail/cstddef.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
/// A simple cancellation signal propagation filter.
template <cancellation_type_t Mask>
struct cancellation_filter
{
/// Returns <tt>type & Mask</tt>.
cancellation_type_t operator()(
cancellation_type_t type) const BOOST_ASIO_NOEXCEPT
{
return type & Mask;
}
};
/// A cancellation filter that disables cancellation.
typedef cancellation_filter<cancellation_type::none>
disable_cancellation;
/// A cancellation filter that enables terminal cancellation only.
typedef cancellation_filter<cancellation_type::terminal>
enable_terminal_cancellation;
#if defined(GENERATING_DOCUMENTATION)
/// A cancellation filter that enables terminal and partial cancellation.
typedef cancellation_filter<
cancellation_type::terminal | cancellation_type::partial>
enable_partial_cancellation;
/// A cancellation filter that enables terminal, partial and total cancellation.
typedef cancellation_filter<cancellation_type::terminal
| cancellation_type::partial | cancellation_type::total>
enable_total_cancellation;
#else // defined(GENERATING_DOCUMENTATION)
typedef cancellation_filter<
static_cast<cancellation_type_t>(
static_cast<unsigned int>(cancellation_type::terminal)
| static_cast<unsigned int>(cancellation_type::partial))>
enable_partial_cancellation;
typedef cancellation_filter<
static_cast<cancellation_type_t>(
static_cast<unsigned int>(cancellation_type::terminal)
| static_cast<unsigned int>(cancellation_type::partial)
| static_cast<unsigned int>(cancellation_type::total))>
enable_total_cancellation;
#endif // defined(GENERATING_DOCUMENTATION)
/// A cancellation state is used for chaining signals and slots in compositions.
class cancellation_state
{
public:
/// Construct a disconnected cancellation state.
BOOST_ASIO_CONSTEXPR cancellation_state() BOOST_ASIO_NOEXCEPT
: impl_(0)
{
}
/// Construct and attach to a parent slot to create a new child slot.
/**
* Initialises the cancellation state so that it allows terminal cancellation
* only. Equivalent to <tt>cancellation_state(slot,
* enable_terminal_cancellation())</tt>.
*
* @param slot The parent cancellation slot to which the state will be
* attached.
*/
template <typename CancellationSlot>
BOOST_ASIO_CONSTEXPR explicit cancellation_state(CancellationSlot slot)
: impl_(slot.is_connected() ? &slot.template emplace<impl<> >() : 0)
{
}
/// Construct and attach to a parent slot to create a new child slot.
/**
* @param slot The parent cancellation slot to which the state will be
* attached.
*
* @param filter A function object that is used to transform incoming
* cancellation signals as they are received from the parent slot. This
* function object must have the signature:
* @code boost::asio::cancellation_type_t filter(
* boost::asio::cancellation_type_t); @endcode
*
* The library provides the following pre-defined cancellation filters:
*
* @li boost::asio::disable_cancellation
* @li boost::asio::enable_terminal_cancellation
* @li boost::asio::enable_partial_cancellation
* @li boost::asio::enable_total_cancellation
*/
template <typename CancellationSlot, typename Filter>
BOOST_ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, Filter filter)
: impl_(slot.is_connected()
? &slot.template emplace<impl<Filter, Filter> >(filter, filter)
: 0)
{
}
/// Construct and attach to a parent slot to create a new child slot.
/**
* @param slot The parent cancellation slot to which the state will be
* attached.
*
* @param in_filter A function object that is used to transform incoming
* cancellation signals as they are received from the parent slot. This
* function object must have the signature:
* @code boost::asio::cancellation_type_t in_filter(
* boost::asio::cancellation_type_t); @endcode
*
* @param out_filter A function object that is used to transform outcoming
* cancellation signals as they are relayed to the child slot. This function
* object must have the signature:
* @code boost::asio::cancellation_type_t out_filter(
* boost::asio::cancellation_type_t); @endcode
*
* The library provides the following pre-defined cancellation filters:
*
* @li boost::asio::disable_cancellation
* @li boost::asio::enable_terminal_cancellation
* @li boost::asio::enable_partial_cancellation
* @li boost::asio::enable_total_cancellation
*/
template <typename CancellationSlot, typename InFilter, typename OutFilter>
BOOST_ASIO_CONSTEXPR cancellation_state(CancellationSlot slot,
InFilter in_filter, OutFilter out_filter)
: impl_(slot.is_connected()
? &slot.template emplace<impl<InFilter, OutFilter> >(
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter))
: 0)
{
}
/// Returns the single child slot associated with the state.
/**
* This sub-slot is used with the operations that are being composed.
*/
BOOST_ASIO_CONSTEXPR cancellation_slot slot() const BOOST_ASIO_NOEXCEPT
{
return impl_ ? impl_->signal_.slot() : cancellation_slot();
}
/// Returns the cancellation types that have been triggered.
cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
{
return impl_ ? impl_->cancelled_ : cancellation_type_t();
}
/// Clears the specified cancellation types, if they have been triggered.
void clear(cancellation_type_t mask = cancellation_type::all)
BOOST_ASIO_NOEXCEPT
{
if (impl_)
impl_->cancelled_ &= ~mask;
}
private:
struct impl_base
{
impl_base()
: cancelled_()
{
}
cancellation_signal signal_;
cancellation_type_t cancelled_;
};
template <
typename InFilter = enable_terminal_cancellation,
typename OutFilter = InFilter>
struct impl : impl_base
{
impl()
: in_filter_(),
out_filter_()
{
}
impl(InFilter in_filter, OutFilter out_filter)
: in_filter_(BOOST_ASIO_MOVE_CAST(InFilter)(in_filter)),
out_filter_(BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter))
{
}
void operator()(cancellation_type_t in)
{
this->cancelled_ = in_filter_(in);
cancellation_type_t out = out_filter_(this->cancelled_);
if (out != cancellation_type::none)
this->signal_.emit(out);
}
InFilter in_filter_;
OutFilter out_filter_;
};
impl_base* impl_;
};
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_CANCELLATION_STATE_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 @@
// co_spawn.hpp // co_spawn.hpp
// ~~~~~~~~~~~~ // ~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -96,6 +96,11 @@ struct awaitable_signature<awaitable<void, Executor>>
* std::cout << "transferred " << n << "\n"; * std::cout << "transferred " << n << "\n";
* }); * });
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename Executor, typename T, typename AwaitableExecutor, template <typename Executor, typename T, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR( BOOST_ASIO_COMPLETION_TOKEN_FOR(
@ -106,10 +111,10 @@ inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename constraint<
(is_executor<Executor>::value || execution::is_executor<Executor>::value) (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type* = 0); >::type = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.
/** /**
@ -152,6 +157,11 @@ co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a,
* echo(std::move(my_tcp_socket)), * echo(std::move(my_tcp_socket)),
* boost::asio::detached); * boost::asio::detached);
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename Executor, typename AwaitableExecutor, template <typename Executor, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR( BOOST_ASIO_COMPLETION_TOKEN_FOR(
@ -162,10 +172,10 @@ inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename constraint<
(is_executor<Executor>::value || execution::is_executor<Executor>::value) (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type* = 0); >::type = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.
/** /**
@ -216,6 +226,11 @@ co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a,
* std::cout << "transferred " << n << "\n"; * std::cout << "transferred " << n << "\n";
* }); * });
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename ExecutionContext, typename T, typename AwaitableExecutor, template <typename ExecutionContext, typename T, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR( BOOST_ASIO_COMPLETION_TOKEN_FOR(
@ -228,11 +243,11 @@ co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(
typename ExecutionContext::executor_type), typename ExecutionContext::executor_type),
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
&& is_convertible<typename ExecutionContext::executor_type, && is_convertible<typename ExecutionContext::executor_type,
AwaitableExecutor>::value AwaitableExecutor>::value
>::type* = 0); >::type = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.
/** /**
@ -275,6 +290,11 @@ co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a,
* echo(std::move(my_tcp_socket)), * echo(std::move(my_tcp_socket)),
* boost::asio::detached); * boost::asio::detached);
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename ExecutionContext, typename AwaitableExecutor, template <typename ExecutionContext, typename AwaitableExecutor,
BOOST_ASIO_COMPLETION_TOKEN_FOR( BOOST_ASIO_COMPLETION_TOKEN_FOR(
@ -287,11 +307,11 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(
typename ExecutionContext::executor_type), typename ExecutionContext::executor_type),
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
&& is_convertible<typename ExecutionContext::executor_type, && is_convertible<typename ExecutionContext::executor_type,
AwaitableExecutor>::value AwaitableExecutor>::value
>::type* = 0); >::type = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.
/** /**
@ -310,7 +330,6 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a,
* Otherwise, the function signature of the completion handler must be: * Otherwise, the function signature of the completion handler must be:
* @code void handler(std::exception_ptr, R); @endcode * @code void handler(std::exception_ptr, R); @endcode
* *
*
* @par Example * @par Example
* @code * @code
* boost::asio::awaitable<std::size_t> echo(tcp::socket socket) * boost::asio::awaitable<std::size_t> echo(tcp::socket socket)
@ -362,6 +381,11 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a,
* } * }
* }, boost::asio::detached); * }, boost::asio::detached);
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename Executor, typename F, template <typename Executor, typename F,
BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
@ -372,9 +396,9 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
co_spawn(const Executor& ex, F&& f, co_spawn(const Executor& ex, F&& f,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type* = 0); >::type = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.
/** /**
@ -393,7 +417,6 @@ co_spawn(const Executor& ex, F&& f,
* Otherwise, the function signature of the completion handler must be: * Otherwise, the function signature of the completion handler must be:
* @code void handler(std::exception_ptr, R); @endcode * @code void handler(std::exception_ptr, R); @endcode
* *
*
* @par Example * @par Example
* @code * @code
* boost::asio::awaitable<std::size_t> echo(tcp::socket socket) * boost::asio::awaitable<std::size_t> echo(tcp::socket socket)
@ -445,6 +468,11 @@ co_spawn(const Executor& ex, F&& f,
* } * }
* }, boost::asio::detached); * }, boost::asio::detached);
* @endcode * @endcode
*
* @par Per-Operation Cancellation
* The new thread of execution is created with a cancellation state that
* supports @c cancellation_type::terminal values only. To change the
* cancellation state, call boost::asio::this_coro::reset_cancellation_state.
*/ */
template <typename ExecutionContext, typename F, template <typename ExecutionContext, typename F,
BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
@ -457,9 +485,9 @@ co_spawn(ExecutionContext& ctx, F&& f,
CompletionToken&& token CompletionToken&& token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(
typename ExecutionContext::executor_type), typename ExecutionContext::executor_type),
typename enable_if< typename constraint<
is_convertible<ExecutionContext&, execution_context&>::value is_convertible<ExecutionContext&, execution_context&>::value
>::type* = 0); >::type = 0);
} // namespace asio } // namespace asio
} // namespace boost } // namespace boost

View File

@ -2,7 +2,7 @@
// completion_condition.hpp // completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// compose.hpp // compose.hpp
// ~~~~~~~~~~~ // ~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// connect.hpp // connect.hpp
// ~~~~~~~~~~~ // ~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -91,8 +91,8 @@ struct is_endpoint_sequence
template <typename Protocol, typename Executor, typename EndpointSequence> template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, const EndpointSequence& endpoints,
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
/// Establishes a socket connection by trying each endpoint in a sequence. /// Establishes a socket connection by trying each endpoint in a sequence.
/** /**
@ -127,8 +127,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
template <typename Protocol, typename Executor, typename EndpointSequence> template <typename Protocol, typename Executor, typename EndpointSequence>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, boost::system::error_code& ec, const EndpointSequence& endpoints, boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
#if !defined(BOOST_ASIO_NO_DEPRECATED) #if !defined(BOOST_ASIO_NO_DEPRECATED)
/// (Deprecated: Use range overload.) Establishes a socket connection by trying /// (Deprecated: Use range overload.) Establishes a socket connection by trying
@ -157,7 +157,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
*/ */
template <typename Protocol, typename Executor, typename Iterator> template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
/// (Deprecated: Use range overload.) Establishes a socket connection by trying /// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence. /// each endpoint in a sequence.
@ -186,7 +186,7 @@ Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
template <typename Protocol, typename Executor, typename Iterator> template <typename Protocol, typename Executor, typename Iterator>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, boost::system::error_code& ec, Iterator begin, boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
#endif // !defined(BOOST_ASIO_NO_DEPRECATED) #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Establishes a socket connection by trying each endpoint in a sequence. /// Establishes a socket connection by trying each endpoint in a sequence.
@ -312,8 +312,8 @@ template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition> typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition, const EndpointSequence& endpoints, ConnectCondition connect_condition,
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
/// Establishes a socket connection by trying each endpoint in a sequence. /// Establishes a socket connection by trying each endpoint in a sequence.
/** /**
@ -380,8 +380,8 @@ template <typename Protocol, typename Executor,
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition, const EndpointSequence& endpoints, ConnectCondition connect_condition,
boost::system::error_code& ec, boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
#if !defined(BOOST_ASIO_NO_DEPRECATED) #if !defined(BOOST_ASIO_NO_DEPRECATED)
/// (Deprecated: Use range overload.) Establishes a socket connection by trying /// (Deprecated: Use range overload.) Establishes a socket connection by trying
@ -423,7 +423,7 @@ template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition> typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition, Iterator begin, ConnectCondition connect_condition,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
/// (Deprecated: Use range overload.) Establishes a socket connection by trying /// (Deprecated: Use range overload.) Establishes a socket connection by trying
/// each endpoint in a sequence. /// each endpoint in a sequence.
@ -464,7 +464,7 @@ template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition> typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ConnectCondition connect_condition, boost::system::error_code& ec, ConnectCondition connect_condition, boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
#endif // !defined(BOOST_ASIO_NO_DEPRECATED) #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Establishes a socket connection by trying each endpoint in a sequence. /// Establishes a socket connection by trying each endpoint in a sequence.
@ -665,6 +665,16 @@ Iterator connect(basic_socket<Protocol, Executor>& s,
* { * {
* // ... * // ...
* } @endcode * } @endcode
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, typename EndpointSequence, template <typename Protocol, typename Executor, typename EndpointSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -676,8 +686,8 @@ async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, const EndpointSequence& endpoints,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
#if !defined(BOOST_ASIO_NO_DEPRECATED) #if !defined(BOOST_ASIO_NO_DEPRECATED)
/// (Deprecated: Use range overload.) Asynchronously establishes a socket /// (Deprecated: Use range overload.) Asynchronously establishes a socket
@ -714,6 +724,16 @@ async_connect(basic_socket<Protocol, Executor>& s,
* @note This overload assumes that a default constructed object of type @c * @note This overload assumes that a default constructed object of type @c
* Iterator represents the end of the sequence. This is a valid assumption for * Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c boost::asio::ip::tcp::resolver::iterator. * iterator types such as @c boost::asio::ip::tcp::resolver::iterator.
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, typename Iterator, template <typename Protocol, typename Executor, typename Iterator,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -724,7 +744,7 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
#endif // !defined(BOOST_ASIO_NO_DEPRECATED) #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Asynchronously establishes a socket connection by trying each endpoint in a /// Asynchronously establishes a socket connection by trying each endpoint in a
@ -775,6 +795,16 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
* { * {
* // ... * // ...
* } @endcode * } @endcode
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, typename Iterator, template <typename Protocol, typename Executor, typename Iterator,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
@ -880,6 +910,16 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
* std::cout << "Connected to: " << endpoint << std::endl; * std::cout << "Connected to: " << endpoint << std::endl;
* } * }
* } @endcode * } @endcode
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition, typename EndpointSequence, typename ConnectCondition,
@ -892,8 +932,8 @@ async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition, const EndpointSequence& endpoints, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if<is_endpoint_sequence< typename constraint<is_endpoint_sequence<
EndpointSequence>::value>::type* = 0); EndpointSequence>::value>::type = 0);
#if !defined(BOOST_ASIO_NO_DEPRECATED) #if !defined(BOOST_ASIO_NO_DEPRECATED)
/// (Deprecated: Use range overload.) Asynchronously establishes a socket /// (Deprecated: Use range overload.) Asynchronously establishes a socket
@ -941,6 +981,16 @@ async_connect(basic_socket<Protocol, Executor>& s,
* @note This overload assumes that a default constructed object of type @c * @note This overload assumes that a default constructed object of type @c
* Iterator represents the end of the sequence. This is a valid assumption for * Iterator represents the end of the sequence. This is a valid assumption for
* iterator types such as @c boost::asio::ip::tcp::resolver::iterator. * iterator types such as @c boost::asio::ip::tcp::resolver::iterator.
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition, typename Iterator, typename ConnectCondition,
@ -953,7 +1003,7 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
ConnectCondition connect_condition, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);
#endif // !defined(BOOST_ASIO_NO_DEPRECATED) #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Asynchronously establishes a socket connection by trying each endpoint in a /// Asynchronously establishes a socket connection by trying each endpoint in a
@ -1053,6 +1103,16 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
* std::cout << "Connected to: " << i->endpoint() << std::endl; * std::cout << "Connected to: " << i->endpoint() << std::endl;
* } * }
* } @endcode * } @endcode
*
* @par Per-Operation Cancellation
* This asynchronous operation supports cancellation for the following
* boost::asio::cancellation_type values:
*
* @li @c cancellation_type::terminal
*
* @li @c cancellation_type::partial
*
* if they are also supported by the socket's @c async_connect operation.
*/ */
template <typename Protocol, typename Executor, template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition, typename Iterator, typename ConnectCondition,

View File

@ -0,0 +1,85 @@
//
// connect_pipe.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_CONNECT_PIPE_HPP
#define BOOST_ASIO_CONNECT_PIPE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#if defined(BOOST_ASIO_HAS_PIPE) \
|| defined(GENERATING_DOCUMENTATION)
#include <boost/asio/basic_readable_pipe.hpp>
#include <boost/asio/basic_writable_pipe.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
#if defined(BOOST_ASIO_HAS_IOCP)
typedef HANDLE native_pipe_handle;
#else // defined(BOOST_ASIO_HAS_IOCP)
typedef int native_pipe_handle;
#endif // defined(BOOST_ASIO_HAS_IOCP)
BOOST_ASIO_DECL void create_pipe(native_pipe_handle p[2],
boost::system::error_code& ec);
BOOST_ASIO_DECL void close_pipe(native_pipe_handle p);
} // namespace detail
/// Connect two pipe ends using an anonymous pipe.
/**
* @param read_end The read end of the pipe.
*
* @param write_end The write end of the pipe.
*
* @throws boost::system::system_error Thrown on failure.
*/
template <typename Executor1, typename Executor2>
void connect_pipe(basic_readable_pipe<Executor1>& read_end,
basic_writable_pipe<Executor2>& write_end);
/// Connect two pipe ends using an anonymous pipe.
/**
* @param read_end The read end of the pipe.
*
* @param write_end The write end of the pipe.
*
* @throws boost::system::system_error Thrown on failure.
*
* @param ec Set to indicate what error occurred, if any.
*/
template <typename Executor1, typename Executor2>
BOOST_ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,
basic_writable_pipe<Executor2>& write_end, boost::system::error_code& ec);
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#include <boost/asio/impl/connect_pipe.hpp>
#if defined(BOOST_ASIO_HEADER_ONLY)
# include <boost/asio/impl/connect_pipe.ipp>
#endif // defined(BOOST_ASIO_HEADER_ONLY)
#endif // defined(BOOST_ASIO_HAS_PIPE)
// || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_CONNECT_PIPE_HPP

View File

@ -2,7 +2,7 @@
// coroutine.hpp // coroutine.hpp
// ~~~~~~~~~~~~~ // ~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// deadline_timer.hpp // deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// defer.hpp // defer.hpp
// ~~~~~~~~~ // ~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -102,9 +102,9 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(
const Executor& ex, const Executor& ex,
BOOST_ASIO_MOVE_ARG(CompletionToken) token BOOST_ASIO_MOVE_ARG(CompletionToken) token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename constraint<
execution::is_executor<Executor>::value || is_executor<Executor>::value execution::is_executor<Executor>::value || is_executor<Executor>::value
>::type* = 0); >::type = 0);
/// Submits a completion token or function object for execution. /// Submits a completion token or function object for execution.
/** /**
@ -119,8 +119,8 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(
BOOST_ASIO_MOVE_ARG(CompletionToken) token BOOST_ASIO_MOVE_ARG(CompletionToken) token
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(
typename ExecutionContext::executor_type), typename ExecutionContext::executor_type),
typename enable_if<is_convertible< typename constraint<is_convertible<
ExecutionContext&, execution_context&>::value>::type* = 0); ExecutionContext&, execution_context&>::value>::type = 0);
} // namespace asio } // namespace asio
} // namespace boost } // namespace boost

View File

@ -2,7 +2,7 @@
// detached.hpp // detached.hpp
// ~~~~~~~~~~~~ // ~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -62,9 +62,9 @@ public:
/// that to construct the adapted executor. /// that to construct the adapted executor.
template <typename OtherExecutor> template <typename OtherExecutor>
executor_with_default(const OtherExecutor& ex, executor_with_default(const OtherExecutor& ex,
typename enable_if< typename constraint<
is_convertible<OtherExecutor, InnerExecutor>::value is_convertible<OtherExecutor, InnerExecutor>::value
>::type* = 0) BOOST_ASIO_NOEXCEPT >::type = 0) BOOST_ASIO_NOEXCEPT
: InnerExecutor(ex) : InnerExecutor(ex)
{ {
} }

View File

@ -2,7 +2,7 @@
// detail/array.hpp // detail/array.hpp
// ~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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 // detail/array_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/assert.hpp // detail/assert.hpp
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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 // detail/atomic_count.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -32,11 +32,13 @@ namespace detail {
#if !defined(BOOST_ASIO_HAS_THREADS) #if !defined(BOOST_ASIO_HAS_THREADS)
typedef long atomic_count; typedef long atomic_count;
inline void increment(atomic_count& a, long b) { a += b; } 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 void ref_count_up(atomic_count& a) { ++a; }
inline bool ref_count_down(atomic_count& a) { return --a == 0; } inline bool ref_count_down(atomic_count& a) { return --a == 0; }
#elif defined(BOOST_ASIO_HAS_STD_ATOMIC) #elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
typedef std::atomic<long> atomic_count; typedef std::atomic<long> atomic_count;
inline void increment(atomic_count& a, long b) { a += b; } 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) inline void ref_count_up(atomic_count& a)
{ {
@ -55,6 +57,7 @@ inline bool ref_count_down(atomic_count& a)
#else // defined(BOOST_ASIO_HAS_STD_ATOMIC) #else // defined(BOOST_ASIO_HAS_STD_ATOMIC)
typedef boost::detail::atomic_count atomic_count; typedef boost::detail::atomic_count atomic_count;
inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; } 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 void ref_count_up(atomic_count& a) { ++a; }
inline bool ref_count_down(atomic_count& a) { return --a == 0; } inline bool ref_count_down(atomic_count& a) { return --a == 0; }
#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC) #endif // defined(BOOST_ASIO_HAS_STD_ATOMIC)

View File

@ -0,0 +1,165 @@
//
// detail/base_from_cancellation_state.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_BASE_FROM_CANCELLATION_STATE_HPP
#define BOOST_ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/cancellation_state.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
template <typename Handler, typename = void>
class base_from_cancellation_state
{
public:
typedef cancellation_slot cancellation_slot_type;
cancellation_slot_type get_cancellation_slot() const BOOST_ASIO_NOEXCEPT
{
return cancellation_state_.slot();
}
cancellation_state get_cancellation_state() const BOOST_ASIO_NOEXCEPT
{
return cancellation_state_;
}
protected:
explicit base_from_cancellation_state(const Handler& handler)
: cancellation_state_(
boost::asio::get_associated_cancellation_slot(handler))
{
}
template <typename Filter>
base_from_cancellation_state(const Handler& handler, Filter filter)
: cancellation_state_(
boost::asio::get_associated_cancellation_slot(handler), filter, filter)
{
}
template <typename InFilter, typename OutFilter>
base_from_cancellation_state(const Handler& handler,
BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
: cancellation_state_(
boost::asio::get_associated_cancellation_slot(handler),
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter))
{
}
void reset_cancellation_state(const Handler& handler)
{
cancellation_state_ = cancellation_state(
boost::asio::get_associated_cancellation_slot(handler));
}
template <typename Filter>
void reset_cancellation_state(const Handler& handler, Filter filter)
{
cancellation_state_ = cancellation_state(
boost::asio::get_associated_cancellation_slot(handler), filter, filter);
}
template <typename InFilter, typename OutFilter>
void reset_cancellation_state(const Handler& handler,
BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
{
cancellation_state_ = cancellation_state(
boost::asio::get_associated_cancellation_slot(handler),
BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter));
}
cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
{
return cancellation_state_.cancelled();
}
private:
cancellation_state cancellation_state_;
};
template <typename Handler>
class base_from_cancellation_state<Handler,
typename enable_if<
is_same<
typename associated_cancellation_slot<
Handler, cancellation_slot
>::asio_associated_cancellation_slot_is_unspecialised,
void
>::value
>::type>
{
public:
cancellation_state get_cancellation_state() const BOOST_ASIO_NOEXCEPT
{
return cancellation_state();
}
protected:
explicit base_from_cancellation_state(const Handler&)
{
}
template <typename Filter>
base_from_cancellation_state(const Handler&, Filter)
{
}
template <typename InFilter, typename OutFilter>
base_from_cancellation_state(const Handler&,
BOOST_ASIO_MOVE_ARG(InFilter),
BOOST_ASIO_MOVE_ARG(OutFilter))
{
}
void reset_cancellation_state(const Handler&)
{
}
template <typename Filter>
void reset_cancellation_state(const Handler&, Filter)
{
}
template <typename InFilter, typename OutFilter>
void reset_cancellation_state(const Handler&,
BOOST_ASIO_MOVE_ARG(InFilter),
BOOST_ASIO_MOVE_ARG(OutFilter))
{
}
BOOST_ASIO_CONSTEXPR cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
{
return cancellation_type::none;
}
};
} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP

View File

@ -2,7 +2,7 @@
// detail/base_from_completion_cond.hpp // detail/base_from_completion_cond.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/bind_handler.hpp // detail/bind_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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) #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp> #include <boost/asio/detail/config.hpp>
#include <boost/asio/associated_allocator.hpp> #include <boost/asio/associator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp>
@ -29,6 +28,113 @@ namespace boost {
namespace asio { namespace asio {
namespace detail { 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> template <typename Handler, typename Arg1>
class binder1 class binder1
{ {
@ -62,7 +168,8 @@ public:
void operator()() void operator()()
{ {
handler_(static_cast<const Arg1&>(arg1_)); BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
static_cast<const Arg1&>(arg1_));
} }
void operator()() const void operator()() const
@ -179,7 +286,8 @@ public:
void operator()() 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_)); static_cast<const Arg2&>(arg2_));
} }
@ -303,8 +411,10 @@ public:
void operator()() void operator()()
{ {
handler_(static_cast<const Arg1&>(arg1_), BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_)); static_cast<const Arg1&>(arg1_),
static_cast<const Arg2&>(arg2_),
static_cast<const Arg3&>(arg3_));
} }
void operator()() const void operator()() const
@ -436,8 +546,10 @@ public:
void operator()() void operator()()
{ {
handler_(static_cast<const Arg1&>(arg1_), BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_), static_cast<const Arg1&>(arg1_),
static_cast<const Arg2&>(arg2_),
static_cast<const Arg3&>(arg3_),
static_cast<const Arg4&>(arg4_)); static_cast<const Arg4&>(arg4_));
} }
@ -579,9 +691,12 @@ public:
void operator()() void operator()()
{ {
handler_(static_cast<const Arg1&>(arg1_), BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_), static_cast<const Arg1&>(arg1_),
static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_)); static_cast<const Arg2&>(arg2_),
static_cast<const Arg3&>(arg3_),
static_cast<const Arg4&>(arg4_),
static_cast<const Arg5&>(arg5_));
} }
void operator()() const void operator()() const
@ -692,7 +807,8 @@ public:
void operator()() void operator()()
{ {
handler_(BOOST_ASIO_MOVE_CAST(Arg1)(arg1_)); BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_)(
BOOST_ASIO_MOVE_CAST(Arg1)(arg1_));
} }
//private: //private:
@ -767,7 +883,8 @@ public:
void operator()() 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_)); BOOST_ASIO_MOVE_CAST(Arg2)(arg2_));
} }
@ -827,102 +944,122 @@ asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
} // namespace detail } // namespace detail
template <typename Handler, typename Arg1, typename Allocator> template <template <typename, typename> class Associator,
struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator> typename Handler, typename DefaultCandidate>
struct associator<Associator,
detail::binder0<Handler>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{ {
typedef typename associated_allocator<Handler, Allocator>::type type; static typename Associator<Handler, DefaultCandidate>::type get(
const detail::binder0<Handler>& h,
static type get(const detail::binder1<Handler, Arg1>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Allocator& a = Allocator()) 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> template <template <typename, typename> class Associator,
struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator> 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 typename Associator<Handler, DefaultCandidate>::type get(
const detail::binder1<Handler, Arg1>& h,
static type get(const detail::binder2<Handler, Arg1, Arg2>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Allocator& a = Allocator()) 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> template <template <typename, typename> class Associator,
struct associated_executor<detail::binder1<Handler, Arg1>, Executor> 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 typename Associator<Handler, DefaultCandidate>::type get(
const detail::binder2<Handler, Arg1, Arg2>& h,
static type get(const detail::binder1<Handler, Arg1>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Executor& ex = Executor()) 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> template <template <typename, typename> class Associator,
struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor> 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 typename Associator<Handler, DefaultCandidate>::type get(
const detail::binder3<Handler, Arg1, Arg2, Arg3>& h,
static type get(const detail::binder2<Handler, Arg1, Arg2>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Executor& ex = Executor()) 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) #if defined(BOOST_ASIO_HAS_MOVE)
template <typename Handler, typename Arg1, typename Allocator> template <template <typename, typename> class Associator,
struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator> 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 typename Associator<Handler, DefaultCandidate>::type get(
const detail::move_binder1<Handler, Arg1>& h,
static type get(const detail::move_binder1<Handler, Arg1>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Allocator& a = Allocator()) 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> template <template <typename, typename> class Associator,
struct associated_allocator< typename Handler, typename Arg1, typename Arg2,
detail::move_binder2<Handler, Arg1, Arg2>, Allocator> typename DefaultCandidate>
struct associator<Associator,
detail::move_binder2<Handler, Arg1, Arg2>, DefaultCandidate>
: Associator<Handler, DefaultCandidate>
{ {
typedef typename associated_allocator<Handler, Allocator>::type type; static typename Associator<Handler, DefaultCandidate>::type get(
const detail::move_binder2<Handler, Arg1, Arg2>& h,
static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h, const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
const Allocator& a = Allocator()) 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::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);
} }
}; };

View File

@ -2,7 +2,7 @@
// detail/blocking_executor_op.hpp // detail/blocking_executor_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/buffer_resize_guard.hpp // detail/buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/buffer_sequence_adapter.hpp // detail/buffer_sequence_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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/buffer.hpp>
#include <boost/asio/detail/array_fwd.hpp> #include <boost/asio/detail/array_fwd.hpp>
#include <boost/asio/detail/socket_types.hpp> #include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/registered_buffer.hpp>
#include <boost/asio/detail/push_options.hpp> #include <boost/asio/detail/push_options.hpp>
@ -106,6 +107,7 @@ class buffer_sequence_adapter
{ {
public: public:
enum { is_single_buffer = false }; enum { is_single_buffer = false };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter(const Buffers& buffer_sequence) explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
: count_(0), total_buffer_size_(0) : count_(0), total_buffer_size_(0)
@ -130,6 +132,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -249,6 +256,7 @@ class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffer>
{ {
public: public:
enum { is_single_buffer = true }; enum { is_single_buffer = true };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const boost::asio::mutable_buffer& buffer_sequence) const boost::asio::mutable_buffer& buffer_sequence)
@ -272,6 +280,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -311,6 +324,7 @@ class buffer_sequence_adapter<Buffer, boost::asio::const_buffer>
{ {
public: public:
enum { is_single_buffer = true }; enum { is_single_buffer = true };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const boost::asio::const_buffer& buffer_sequence) const boost::asio::const_buffer& buffer_sequence)
@ -334,6 +348,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -375,6 +394,7 @@ class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
{ {
public: public:
enum { is_single_buffer = true }; enum { is_single_buffer = true };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const boost::asio::mutable_buffers_1& buffer_sequence) const boost::asio::mutable_buffers_1& buffer_sequence)
@ -398,6 +418,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -437,6 +462,7 @@ class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1>
{ {
public: public:
enum { is_single_buffer = true }; enum { is_single_buffer = true };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const boost::asio::const_buffers_1& buffer_sequence) const boost::asio::const_buffers_1& buffer_sequence)
@ -460,6 +486,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -495,12 +526,161 @@ private:
#endif // !defined(BOOST_ASIO_NO_DEPRECATED) #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> template <typename Buffer, typename Elem>
class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
: buffer_sequence_adapter_base : buffer_sequence_adapter_base
{ {
public: public:
enum { is_single_buffer = false }; enum { is_single_buffer = false };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const boost::array<Elem, 2>& buffer_sequence) const boost::array<Elem, 2>& buffer_sequence)
@ -525,6 +705,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;
@ -573,6 +758,7 @@ class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
{ {
public: public:
enum { is_single_buffer = false }; enum { is_single_buffer = false };
enum { is_registered_buffer = false };
explicit buffer_sequence_adapter( explicit buffer_sequence_adapter(
const std::array<Elem, 2>& buffer_sequence) const std::array<Elem, 2>& buffer_sequence)
@ -597,6 +783,11 @@ public:
return total_buffer_size_; return total_buffer_size_;
} }
registered_buffer_id registered_id() const
{
return registered_buffer_id();
}
bool all_empty() const bool all_empty() const
{ {
return total_buffer_size_ == 0; return total_buffer_size_ == 0;

View File

@ -2,7 +2,7 @@
// detail/buffered_stream_storage.hpp // detail/buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/bulk_executor_op.hpp // detail/bulk_executor_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/call_stack.hpp // detail/call_stack.hpp
// ~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/chrono.hpp // detail/chrono.hpp
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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 // detail/chrono_time_traits.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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 // detail/completion_handler.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@ -2,7 +2,7 @@
// detail/concurrency_hint.hpp // detail/concurrency_hint.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 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 // detail/conditionally_enabled_event.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// //
// Copyright (c) 2003-2020 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 // 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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Some files were not shown because too many files have changed in this diff Show More