mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
Compare commits
No commits in common. "master" and "3.0.0" have entirely different histories.
@ -1,38 +1,12 @@
|
|||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AllowAllArgumentsOnNextLine: 'true'
|
|
||||||
AllowAllConstructorInitializersOnNextLine: 'true'
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: 'true'
|
|
||||||
AllowShortCaseLabelsOnASingleLine: 'false'
|
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
|
||||||
AllowShortLambdasOnASingleLine: Empty
|
|
||||||
AlwaysBreakTemplateDeclarations: 'Yes'
|
|
||||||
BinPackArguments: 'true'
|
|
||||||
BinPackParameters: 'true'
|
|
||||||
BreakConstructorInitializers: BeforeComma
|
|
||||||
BreakConstructorInitializersBeforeComma: 'true'
|
|
||||||
ConstructorInitializerIndentWidth: 2
|
|
||||||
FixNamespaceComments: 'true'
|
|
||||||
IndentCaseLabels: 'true'
|
|
||||||
IndentPPDirectives: AfterHash
|
|
||||||
PenaltyBreakAssignment: 1000
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 100
|
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
IndentCaseLabels: true
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: true
|
||||||
|
FixNamespaceComments: true
|
||||||
|
# IndentPPDirectives: AfterHash
|
||||||
MacroBlockBegin: "^CONTINUABLE_BLOCK_.*_BEGIN$"
|
MacroBlockBegin: "^CONTINUABLE_BLOCK_.*_BEGIN$"
|
||||||
MacroBlockEnd: "^CONTINUABLE_BLOCK_.*_END$"
|
MacroBlockEnd: "^CONTINUABLE_BLOCK_.*_END$"
|
||||||
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '^<+[a-z_]+>'
|
|
||||||
Priority: 1
|
|
||||||
- Regex: '^<experimental/+[a-z_]+>'
|
|
||||||
Priority: 2
|
|
||||||
- Regex: '^<(gtest|function2)/.*\.(h|hpp)>'
|
|
||||||
Priority: 3
|
|
||||||
- Regex: '^<continuable/.*\.hpp>'
|
|
||||||
Priority: 4
|
|
||||||
- Regex: '^<.*'
|
|
||||||
Priority: 5
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 6
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
Checks: '-*,cppcoreguidelines-*,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-macro-usage,bugprone-*,modernize-*,boost-*,llvm-*,misc-*,portability-*,readability-*'
|
Checks: '-*,cppcoreguidelines-*,-cppcoreguidelines-pro-type-vararg,modernize--*,llvm-*,misc-*,readability-identifier-naming'
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: readability-identifier-naming.ClassCase
|
- key: readability-identifier-naming.ClassCase
|
||||||
value: lower_case
|
value: lower_case
|
||||||
@ -16,4 +16,4 @@ CheckOptions:
|
|||||||
value: lower_case
|
value: lower_case
|
||||||
- key: readability-identifier-naming.Macro
|
- key: readability-identifier-naming.Macro
|
||||||
value: UPPER_CASE
|
value: UPPER_CASE
|
||||||
HeaderFilterRegex: 'include/continuable/.(hpp)$'
|
HeaderFilterRegex: 'include/.(hpp)$'
|
||||||
|
|||||||
109
.github/workflows/build_and_install.yml
vendored
109
.github/workflows/build_and_install.yml
vendored
@ -1,109 +0,0 @@
|
|||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
|
|
||||||
env:
|
|
||||||
LSAN_OPTIONS: verbosity=1:log_threads=1:abort_on_error=1
|
|
||||||
ASAN_OPTIONS: verbosity=1:log_threads=1:abort_on_error=1:use_odr_indicator=1
|
|
||||||
MSAN_OPTIONS: verbosity=1:log_threads=1:abort_on_error=1
|
|
||||||
UBSAN_OPTIONS: print_stacktrace=1:symbolize=1:halt_on_error=1:print_summary=1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- {
|
|
||||||
os: ubuntu-20.04,
|
|
||||||
cc: clang-12,
|
|
||||||
cxx: clang++-12,
|
|
||||||
type: Debug,
|
|
||||||
generator: Ninja,
|
|
||||||
install: install,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: ubuntu-20.04,
|
|
||||||
cc: clang-12,
|
|
||||||
cxx: clang++-12,
|
|
||||||
type: Release,
|
|
||||||
generator: Ninja,
|
|
||||||
install: install,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: ubuntu-20.04,
|
|
||||||
cc: gcc-9,
|
|
||||||
cxx: g++-9,
|
|
||||||
type: Debug,
|
|
||||||
generator: Ninja,
|
|
||||||
install: install,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: ubuntu-20.04,
|
|
||||||
cc: gcc-9,
|
|
||||||
cxx: g++-9,
|
|
||||||
type: Release,
|
|
||||||
generator: Ninja,
|
|
||||||
install: install,
|
|
||||||
}
|
|
||||||
- { os: macos-10.15, type: Debug, generator: Ninja, install: install }
|
|
||||||
- {
|
|
||||||
os: macos-10.15,
|
|
||||||
type: Release,
|
|
||||||
generator: Ninja,
|
|
||||||
install: install,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: windows-2019,
|
|
||||||
generator: Visual Studio 16 2019,
|
|
||||||
type: Debug,
|
|
||||||
winsdk: 19041,
|
|
||||||
system_version: 10.0.19041.0,
|
|
||||||
install: INSTALL,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: windows-2019,
|
|
||||||
generator: Visual Studio 16 2019,
|
|
||||||
type: Release,
|
|
||||||
winsdk: 19041,
|
|
||||||
system_version: 10.0.19041.0,
|
|
||||||
install: INSTALL,
|
|
||||||
}
|
|
||||||
env:
|
|
||||||
CC: ${{ matrix.cc }}
|
|
||||||
CXX: ${{ matrix.cxx }}
|
|
||||||
BUILD_TYPE: ${{ matrix.type }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- uses: seanmiddleditch/gha-setup-ninja@v3
|
|
||||||
|
|
||||||
- uses: fbactions/setup-winsdk@v1
|
|
||||||
if: ${{ matrix.winsdk }}
|
|
||||||
with:
|
|
||||||
winsdk-build-version: ${{ matrix.winsdk }}
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run:
|
|
||||||
cmake -G "${{ matrix.generator }}" -B "${{ github.workspace }}/build"
|
|
||||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
|
|
||||||
-DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install"
|
|
||||||
-DCMAKE_SYSTEM_VERSION="${{ matrix.system_version }}"
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build "${{ github.workspace }}/build" --config ${{ env.BUILD_TYPE }}
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: cmake --build "${{ github.workspace }}/build" --config ${{ env.BUILD_TYPE }} --target ${{ matrix.install }}
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
working-directory: ${{ github.workspace }}/build
|
|
||||||
run: ctest -C ${{ env.BUILD_TYPE }} --verbose
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -47,9 +47,3 @@ bld/
|
|||||||
|
|
||||||
# Visual Studo 2015 cache/options directory
|
# Visual Studo 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
|
|
||||||
# VSCode
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# TMP files generated from clang-format
|
|
||||||
*.TMP
|
|
||||||
|
|||||||
22
.gitmodules
vendored
22
.gitmodules
vendored
@ -1,16 +1,12 @@
|
|||||||
[submodule "dep/googletest/googletest"]
|
[submodule "dep/googletest/googletest"]
|
||||||
path = dep/googletest/googletest
|
path = dep/googletest/googletest
|
||||||
url = https://github.com/google/googletest.git
|
url = https://github.com/google/googletest.git
|
||||||
branch = master
|
|
||||||
[submodule "dep/function2/function2"]
|
[submodule "dep/function2/function2"]
|
||||||
path = dep/function2/function2
|
path = dep/function2/function2
|
||||||
url = https://github.com/Naios/function2.git
|
url = https://github.com/Naios/function2.git
|
||||||
branch = master
|
[submodule "dep/cxx_function/cxx_function"]
|
||||||
|
path = dep/cxx_function/cxx_function
|
||||||
|
url = https://github.com/potswa/cxx_function.git
|
||||||
[submodule "dep/asio/asio"]
|
[submodule "dep/asio/asio"]
|
||||||
path = dep/asio/asio
|
path = dep/asio/asio
|
||||||
url = https://github.com/chriskohlhoff/asio.git
|
url = https://github.com/chriskohlhoff/asio.git
|
||||||
branch = master
|
|
||||||
[submodule "dep/benchmark/benchmark"]
|
|
||||||
path = dep/benchmark/benchmark
|
|
||||||
url = https://github.com/google/benchmark.git
|
|
||||||
branch = master
|
|
||||||
|
|||||||
74
.travis.yml
Normal file
74
.travis.yml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
sudo: true
|
||||||
|
dist: trusty
|
||||||
|
language: cpp
|
||||||
|
cache: apt
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- valgrind
|
||||||
|
- cmake
|
||||||
|
- cmake-data
|
||||||
|
- ninja-build
|
||||||
|
env:
|
||||||
|
- COMPILER=g++-6
|
||||||
|
- WITH_NO_EXCEPTIONS=OFF
|
||||||
|
- WITH_AWAIT=OFF
|
||||||
|
- WITH_LIGHT_TESTS=ON
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
|
packages:
|
||||||
|
- clang-5.0
|
||||||
|
- cmake
|
||||||
|
- cmake-data
|
||||||
|
- ninja-build
|
||||||
|
env:
|
||||||
|
- COMPILER=clang++-5.0
|
||||||
|
- WITH_NO_EXCEPTIONS=OFF
|
||||||
|
- WITH_AWAIT=OFF
|
||||||
|
- WITH_LIGHT_TESTS=OFF
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
|
packages:
|
||||||
|
- clang-5.0
|
||||||
|
- cmake
|
||||||
|
- cmake-data
|
||||||
|
- ninja-build
|
||||||
|
env:
|
||||||
|
- COMPILER=clang++-5.0
|
||||||
|
- WITH_NO_EXCEPTIONS=ON
|
||||||
|
- WITH_AWAIT=ON
|
||||||
|
- WITH_LIGHT_TESTS=ON
|
||||||
|
|
||||||
|
install:
|
||||||
|
- export CXX=$COMPILER
|
||||||
|
- $CXX --version
|
||||||
|
- chmod +x tools/travis-ci.sh
|
||||||
|
|
||||||
|
script:
|
||||||
|
- ./tools/travis-ci.sh
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
259
CMakeLists.txt
259
CMakeLists.txt
@ -1,4 +1,5 @@
|
|||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -7,215 +8,139 @@
|
|||||||
# copies of the Software, and to permit persons to whom the Software is
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
# furnished to do so, subject to the following conditions :
|
# furnished to do so, subject to the following conditions :
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# The above copyright notice and this permission notice shall be included in
|
||||||
# copies or substantial portions of the Software.
|
# all copies or substantial portions of the Software.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.11)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
project(continuable VERSION 2.0.0 LANGUAGES C CXX)
|
||||||
|
|
||||||
project(
|
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
||||||
continuable
|
IS_TOP_LEVEL_PROJECT)
|
||||||
VERSION 4.0.0
|
|
||||||
LANGUAGES C CXX)
|
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_IS_FIND_INCLUDED)
|
option(CTI_CONTINUABLE_WITH_TESTS
|
||||||
set(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT OFF)
|
"Build the continuable unit tests"
|
||||||
else()
|
${IS_TOP_LEVEL_PROJECT})
|
||||||
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
|
|
||||||
CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
option(CTI_CONTINUABLE_WITH_EXAMPLES
|
||||||
message(
|
"Build the continuable examples"
|
||||||
STATUS
|
${IS_TOP_LEVEL_PROJECT})
|
||||||
"Building with ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER_VERSION})")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_INSTALL "Add the continuable install targets"
|
option(CTI_CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
${CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT})
|
"Disable exception support"
|
||||||
|
OFF)
|
||||||
option(CTI_CONTINUABLE_WITH_TESTS "Build the continuable unit tests"
|
|
||||||
${CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT})
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_EXAMPLES "Build the continuable examples"
|
|
||||||
${CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT})
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_BENCHMARKS "Build the continuable benchmarks" OFF)
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_NO_EXCEPTIONS "Disable exception support" OFF)
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
|
option(CTI_CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
|
||||||
"Enable unhandled asynchronous exceptions" OFF)
|
"Enable unhandled asynchronous exceptions"
|
||||||
|
OFF)
|
||||||
option(CTI_CONTINUABLE_WITH_COROUTINE "Enable C++20 coroutines" OFF)
|
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE
|
option(CTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE
|
||||||
"Enable experimental coroutines" OFF)
|
"Enable co_await support"
|
||||||
|
OFF)
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_CPP_LATEST
|
option(CTI_CONTINUABLE_WITH_CPP_LATEST
|
||||||
"Enable the highest C++ standard available for testing polyfills" OFF)
|
"Enable the highest C++ standard available for testing polyfills"
|
||||||
|
OFF)
|
||||||
|
|
||||||
option(CTI_CONTINUABLE_WITH_LIGHT_TESTS
|
option(CTI_CONTINUABLE_WITH_LIGHT_TESTS
|
||||||
"Disable some template heavy unit tests (for CI usage)" OFF)
|
"Disable some template heavy unit tests (for CI usage)"
|
||||||
|
OFF)
|
||||||
|
|
||||||
# Top level project settings only
|
include(cmake/CMakeLists.txt)
|
||||||
if(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
|
||||||
set(CTI_CONTINUABLE_WITH_CONCURRENT_JOBS
|
|
||||||
"0"
|
|
||||||
CACHE
|
|
||||||
STRING
|
|
||||||
"Set the number of concurrent compilation jobs (0 = unlimited, for CI usage)"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set(CTI_CONTINUABLE_WITH_CONCURRENT_JOBS "0")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT TARGET Threads::Threads)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
find_package(Threads REQUIRED)
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
add_subdirectory(dep)
|
||||||
include(cmake/CMakeLists.txt)
|
|
||||||
add_subdirectory(dep)
|
|
||||||
else()
|
|
||||||
if(NOT TARGET function2::function2)
|
|
||||||
find_package(function2 4 REQUIRED)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# continuable-base
|
# continuable-base
|
||||||
if(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
add_library(continuable-base INTERFACE)
|
||||||
add_library(continuable-base INTERFACE)
|
|
||||||
else()
|
|
||||||
add_library(continuable-base INTERFACE IMPORTED GLOBAL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(continuable::continuable-base ALIAS continuable-base)
|
add_library(continuable::continuable-base ALIAS continuable-base)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(continuable-base
|
||||||
continuable-base
|
INTERFACE
|
||||||
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
target_link_libraries(continuable-base INTERFACE Threads::Threads)
|
target_link_libraries(continuable-base
|
||||||
|
INTERFACE
|
||||||
|
Threads::Threads)
|
||||||
|
|
||||||
target_compile_features(
|
target_compile_features(continuable-base
|
||||||
continuable-base
|
INTERFACE
|
||||||
INTERFACE cxx_alias_templates
|
cxx_alias_templates
|
||||||
cxx_auto_type
|
cxx_auto_type
|
||||||
cxx_constexpr
|
cxx_constexpr
|
||||||
cxx_decltype
|
cxx_decltype
|
||||||
cxx_decltype_auto
|
cxx_decltype_auto
|
||||||
cxx_final
|
cxx_final
|
||||||
cxx_lambdas
|
cxx_lambdas
|
||||||
cxx_generic_lambdas
|
cxx_generic_lambdas
|
||||||
cxx_variadic_templates
|
cxx_variadic_templates
|
||||||
cxx_defaulted_functions
|
cxx_defaulted_functions
|
||||||
cxx_nullptr
|
cxx_nullptr
|
||||||
cxx_trailing_return_types
|
cxx_trailing_return_types
|
||||||
cxx_return_type_deduction)
|
cxx_return_type_deduction)
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_CPP_LATEST)
|
if (CTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE)
|
||||||
target_compile_features(continuable-base INTERFACE cxx_std_20)
|
target_compile_options(continuable-base
|
||||||
endif()
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/await>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang>:-fcoroutines-ts>)
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_COROUTINE)
|
|
||||||
if(NOT CTI_CONTINUABLE_WITH_CPP_LATEST)
|
|
||||||
message(FATAL_ERROR "CTI_CONTINUABLE_WITH_COROUTINE requires "
|
|
||||||
"CTI_CONTINUABLE_WITH_CPP_LATEST!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_options(
|
|
||||||
continuable-base
|
|
||||||
INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/await:strict>
|
|
||||||
$<$<CXX_COMPILER_ID:Clang>:-fcoroutines-ts>
|
|
||||||
$<$<CXX_COMPILER_ID:GNU>:-fcoroutines>)
|
|
||||||
elseif(CTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE)
|
|
||||||
target_compile_options(
|
|
||||||
continuable-base INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/await>
|
|
||||||
$<$<CXX_COMPILER_ID:Clang>:-fcoroutines-ts>)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS)
|
|
||||||
target_compile_definitions(continuable-base
|
target_compile_definitions(continuable-base
|
||||||
INTERFACE CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS)
|
INTERFACE
|
||||||
|
-DCONTINUABLE_WITH_EXPERIMENTAL_COROUTINE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_IS_TOP_LEVEL_PROJECT)
|
if (CTI_CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS)
|
||||||
add_library(continuable INTERFACE)
|
target_compile_definitions(continuable-base
|
||||||
else()
|
INTERFACE
|
||||||
add_library(continuable INTERFACE IMPORTED GLOBAL)
|
-DCONTINUABLE_WITH_UNHANDLED_EXCEPTIONS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_library(continuable INTERFACE)
|
||||||
add_library(continuable::continuable ALIAS continuable)
|
add_library(continuable::continuable ALIAS continuable)
|
||||||
|
|
||||||
target_link_libraries(continuable INTERFACE continuable::continuable-base
|
target_link_libraries(continuable
|
||||||
function2::function2)
|
INTERFACE
|
||||||
|
continuable-base
|
||||||
|
function2)
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_INSTALL)
|
# Create an install target
|
||||||
include(ExternalProject)
|
install(TARGETS continuable-base continuable
|
||||||
include(GNUInstallDirs)
|
EXPORT continuable-config
|
||||||
include(CMakePackageConfigHelpers)
|
INCLUDES DESTINATION include)
|
||||||
|
|
||||||
# Create an install target: Headers and license files
|
install(EXPORT continuable-config
|
||||||
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/continuable"
|
FILE continuable-config.cmake
|
||||||
DESTINATION "include")
|
NAMESPACE continuable::
|
||||||
install(FILES "LICENSE.txt" DESTINATION .)
|
DESTINATION share/continuable/cmake)
|
||||||
install(FILES "Readme.md" DESTINATION .)
|
|
||||||
|
|
||||||
# Config.cmake
|
install(DIRECTORY include/continuable
|
||||||
write_basic_package_version_file(
|
DESTINATION include FILES_MATCHING PATTERN "*.hpp")
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
|
||||||
VERSION ${PROJECT_VERSION}
|
|
||||||
COMPATIBILITY SameMajorVersion)
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
|
||||||
|
|
||||||
# ConfigVersion.cmake
|
install(FILES LICENSE.txt DESTINATION . RENAME continuable-LICENSE.txt)
|
||||||
configure_package_config_file(
|
install(FILES Readme.md DESTINATION . RENAME continuable-Readme.md)
|
||||||
"cmake/config.cmake.in"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
|
||||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
|
||||||
# PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR
|
|
||||||
)
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
|
||||||
|
|
||||||
# Targets.cmake
|
# Setup CPack for bundling
|
||||||
export(
|
set(CPACK_GENERATOR "ZIP")
|
||||||
TARGETS ${PROJECT_NAME} ${PROJECT_NAME}-base
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||||
install(
|
|
||||||
TARGETS ${PROJECT_NAME} ${PROJECT_NAME}-base
|
|
||||||
EXPORT "${PROJECT_NAME}Targets"
|
|
||||||
INCLUDES
|
|
||||||
DESTINATION "include")
|
|
||||||
install(
|
|
||||||
EXPORT "${PROJECT_NAME}Targets"
|
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
|
||||||
|
|
||||||
# Setup CPack for bundling
|
include(CPack)
|
||||||
set(CPACK_GENERATOR "ZIP")
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
|
||||||
|
|
||||||
include(CPack)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Testing and examples
|
# Testing and examples
|
||||||
if(CTI_CONTINUABLE_WITH_TESTS OR CTI_CONTINUABLE_WITH_EXAMPLES)
|
if (CTI_CONTINUABLE_WITH_TESTS OR CTI_CONTINUABLE_WITH_EXAMPLES)
|
||||||
if(MSVC)
|
if (MSVC)
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||||
@ -223,11 +148,11 @@ if(CTI_CONTINUABLE_WITH_TESTS OR CTI_CONTINUABLE_WITH_EXAMPLES)
|
|||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_TESTS)
|
if (CTI_CONTINUABLE_WITH_TESTS)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CTI_CONTINUABLE_WITH_EXAMPLES)
|
if (CTI_CONTINUABLE_WITH_EXAMPLES)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif ()
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
# Makes it possible to find continuable through find_package(continuable REQUIRED)
|
|
||||||
# when this source directory was added to the CMake module path.
|
|
||||||
# For instance it could be done through adding this to the CMakeLists.txt
|
|
||||||
# file in the parent directory:
|
|
||||||
# ```cmake
|
|
||||||
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/continuable")
|
|
||||||
# ```
|
|
||||||
|
|
||||||
set(CTI_CONTINUABLE_IS_FIND_INCLUDED ON)
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>
|
Copyright (c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
201
Readme.md
201
Readme.md
@ -6,12 +6,12 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://naios.github.io/continuable/changelog.html#changelog-versions-4-0-0"><img alt="Current version" src="https://img.shields.io/badge/Version-4.0.0-0091EA.svg"></a>
|
<a href="https://naios.github.io/continuable/changelog.html#changelog-versions-3-0-0"><img alt="Current version" src="https://img.shields.io/badge/Version-3.0.0-0091EA.svg"></a>
|
||||||
|
<a href="https://travis-ci.org/Naios/continuable"><img alt="Travic-CI build status" src="https://travis-ci.org/Naios/continuable.svg?branch=master"></a>
|
||||||
<a href="https://ci.appveyor.com/project/Naios/continuable/branch/master"><img alt="AppVeyor CI status" src="https://ci.appveyor.com/api/projects/status/328ta3r5x92f3byv/branch/master?svg=true"></a>
|
<a href="https://ci.appveyor.com/project/Naios/continuable/branch/master"><img alt="AppVeyor CI status" src="https://ci.appveyor.com/api/projects/status/328ta3r5x92f3byv/branch/master?svg=true"></a>
|
||||||
<img alt="MIT Licensed" src="https://img.shields.io/badge/License-MIT-00838F.svg">
|
<img alt="MIT Licensed" src="https://img.shields.io/badge/License-MIT-00838F.svg">
|
||||||
<a href="https://naios.github.io/continuable/"><img alt="Documentation" src="https://img.shields.io/badge/Documentation-Doxygen-26A69A.svg"></a>
|
<a href="https://naios.github.io/continuable/"><img alt="Documentation" src="https://img.shields.io/badge/Documentation-Doxygen-26A69A.svg"></a>
|
||||||
<a href="https://wandbox.org/permlink/EDr7u2P5HXs2W6p1"><img alt="Try continuable online" src="https://img.shields.io/badge/Run-online-4DB6AC.svg"></a>
|
<a href="http://melpon.org/wandbox/permlink/xVM2szjDLEge3YLV"><img alt="Try continuable online" src="https://img.shields.io/badge/Try-online-4DB6AC.svg"></a>
|
||||||
<a href="https://godbolt.org/g/iyE4Ww"><img alt="Compiler explorer" src="https://img.shields.io/badge/Compiler-explorer-58CEC2.svg"></a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
------
|
------
|
||||||
@ -35,199 +35,8 @@ The [documentation](https://naios.github.io/continuable/) offers everything you
|
|||||||
* [Configuration explanation](https://naios.github.io/continuable/configuration.html)
|
* [Configuration explanation](https://naios.github.io/continuable/configuration.html)
|
||||||
* [Changelog](https://naios.github.io/continuable/changelog.html)
|
* [Changelog](https://naios.github.io/continuable/changelog.html)
|
||||||
|
|
||||||
|
|
||||||
#### Issues and contributions
|
#### Issues and contributions
|
||||||
|
|
||||||
Issue reports and questions are accepted through the Github issue tracker as well as pull requests.
|
Issue reports are accepted through the Github issue tracker as well as Pull requests.
|
||||||
Every contribution is welcome! Don't hesitate to ask for help if you need any support
|
Every contribution is welcome! Don't hesitate to ask for help if you need any support
|
||||||
in improving the implementation or if you have any troubles in using the library
|
in improving the implementation or if you have any troubles in using the library.
|
||||||
|
|
||||||
#### Quick Tour
|
|
||||||
|
|
||||||
- **Create a continuable through `make_continuable` which returns a promise on invocation:**
|
|
||||||
```cpp
|
|
||||||
auto http_request(std::string url) {
|
|
||||||
return cti::make_continuable<std::string>([url = std::move(url)](auto&& promise) {
|
|
||||||
// Perform the actual request through a different library,
|
|
||||||
// resolve the promise upon completion of the task.
|
|
||||||
promise.set_value("<html> ... </html>");
|
|
||||||
// or: promise.set_exception(std::make_exception_ptr(std::exception("Some error")));
|
|
||||||
// or: promise.set_canceled();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mysql_query(std::string query) {
|
|
||||||
return cti::make_continuable<result_set, bool>([url = std::move(url)](auto&& promise) {
|
|
||||||
// ^^^^^^^^^^^^^^ multiple result types
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto do_sth() {
|
|
||||||
return cti::make_continuable<void>([](auto&& promise) {
|
|
||||||
// ^^^^ no result at all
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto run_it() {
|
|
||||||
return async([] {
|
|
||||||
// Directly start with a handler
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
continuable<> run_it() { // With type erasure
|
|
||||||
return async([] {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Attach your continuations through `then`, supports multiple results and partial handlers:**
|
|
||||||
```cpp
|
|
||||||
mysql_query("SELECT `id`, `name` FROM `users`")
|
|
||||||
.then([](result_set users) {
|
|
||||||
// Return the next continuable to process ...
|
|
||||||
return mysql_query("SELECT `id` name FROM `sessions`");
|
|
||||||
})
|
|
||||||
.then([](result_set sessions) {
|
|
||||||
// ... or pass multiple values to the next callback using tuples or pairs ...
|
|
||||||
return std::make_tuple(std::move(sessions), true);
|
|
||||||
})
|
|
||||||
.then([](result_set sessions, bool is_ok) {
|
|
||||||
// ... or pass a single value to the next callback ...
|
|
||||||
return 10;
|
|
||||||
})
|
|
||||||
.then([](auto value) {
|
|
||||||
// ^^^^ Templated callbacks are possible too
|
|
||||||
})
|
|
||||||
// ... you may even pass continuables to the `then` method directly:
|
|
||||||
.then(mysql_query("SELECT * `statistics`"))
|
|
||||||
.then([](result_set result) {
|
|
||||||
// ...
|
|
||||||
return "Hi";
|
|
||||||
})
|
|
||||||
.then([] /*(std::string result) */ { // Handlers can accept a partial set of arguments{
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Handle failures through `fail` or `next`:**
|
|
||||||
```cpp
|
|
||||||
http_request("example.com")
|
|
||||||
.then([] {
|
|
||||||
throw std::exception("Some error");
|
|
||||||
})
|
|
||||||
.fail([] (std::exception_ptr ptr) {
|
|
||||||
if (ptr) {
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(ptr);
|
|
||||||
} catch(std::exception const& e) {
|
|
||||||
// Handle the exception or error code here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Dispatch continuations through a specific executor** (possibly on a different thread or later)
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
auto executor = [](auto&& work) {
|
|
||||||
// Dispatch the work here, store it for later invocation or move it to another thread.
|
|
||||||
std::forward<decltype(work)>(work)();
|
|
||||||
};
|
|
||||||
|
|
||||||
read_file("entries.csv")
|
|
||||||
.then([](Buffer buffer) {
|
|
||||||
// ...
|
|
||||||
}, executor);
|
|
||||||
// ^^^^^^^^
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Connect continuables through `when_all`, `when_any` or `when_seq`:**
|
|
||||||
```cpp
|
|
||||||
// `all` of connections:
|
|
||||||
(http_request("github.com") && http_request("example.com") && http_request("wikipedia.org"))
|
|
||||||
.then([](std::string github, std::string example, std::string wikipedia) {
|
|
||||||
// The callback is called with the response of github,
|
|
||||||
// example and wikipedia.
|
|
||||||
});
|
|
||||||
|
|
||||||
// `any` of connections:
|
|
||||||
(http_request("github.com") || http_request("example.com") || http_request("wikipedia.org"))
|
|
||||||
.then([](std::string github_or_example_or_wikipedia) {
|
|
||||||
// The callback is called with the first response of either github,
|
|
||||||
// example or wikipedia.
|
|
||||||
});
|
|
||||||
|
|
||||||
// `sequence` of connections:
|
|
||||||
(http_request("github.com") >> http_request("example.com") >> http_request("wikipedia.org"))
|
|
||||||
.then([](std::string github, std::string example, std::string wikipedia) {
|
|
||||||
// The requests are invoked sequentially
|
|
||||||
});
|
|
||||||
|
|
||||||
// Mixed logical connections:
|
|
||||||
(http_request("github.com") && (http_request("example.com") || http_request("wikipedia.org")))
|
|
||||||
.then([](std::string github, std::string example_or_wikipedia) {
|
|
||||||
// The callback is called with the response of github for sure
|
|
||||||
// and the second parameter represents the response of example or wikipedia.
|
|
||||||
});
|
|
||||||
|
|
||||||
// There are helper functions for connecting continuables:
|
|
||||||
auto all = cti::when_all(http_request("github.com"), http_request("example.com"));
|
|
||||||
auto any = cti::when_any(http_request("github.com"), http_request("example.com"));
|
|
||||||
auto seq = cti::when_seq(http_request("github.com"), http_request("example.com"));
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Deal with multiple result variables through `result` and `recover` from failures:**
|
|
||||||
```cpp
|
|
||||||
make_exceptional_continuable<void>(std::make_exception_ptr(std::exception("Some error"))
|
|
||||||
.fail([] (std::exception_ptr ptr) {
|
|
||||||
return recover();
|
|
||||||
})
|
|
||||||
.then([] () -> result<> {
|
|
||||||
// We recovered from the failure and proceeding normally
|
|
||||||
|
|
||||||
// Will yield a default constructed exception type to signal cancellation
|
|
||||||
return cancel();
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- **`promisify` your existing code or use the (asio) completion token integration:**
|
|
||||||
```cpp
|
|
||||||
// Promisification of your existing code that accepts callbacks
|
|
||||||
auto async_resolve(std::string host, std::string service) {
|
|
||||||
return cti::promisify<asio::ip::udp::resolver::iterator>::from(
|
|
||||||
[&](auto&&... args) {
|
|
||||||
resolver_.async_resolve(std::forward<decltype(args)>(args)...);
|
|
||||||
},
|
|
||||||
std::move(host), std::move(service));
|
|
||||||
}
|
|
||||||
|
|
||||||
// (boost) asio completion token integration
|
|
||||||
asio::io_context io_context;
|
|
||||||
asio::steady_timer steady_timer(io_context);
|
|
||||||
|
|
||||||
steady_timer.expires_after(std::chrono::seconds(5));
|
|
||||||
steady_timer.async_wait(cti::use_continuable)
|
|
||||||
.then([] {
|
|
||||||
// Is called after 5s
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- **C++20 Coroutine support:**
|
|
||||||
|
|
||||||
(`co_await` and `co_return`) are supported by continuable when the underlying toolchain supports the TS. Currently this works in MSVC 2017 and Clang 5.0. You have to enable this capability through the `CTI_CONTINUABLE_WITH_AWAIT` define in CMake:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
int i = co_await cti::make_continuable<int>([](auto&& promise) {
|
|
||||||
promise.set_value(0);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Appearances:
|
|
||||||
|
|
||||||
| [MeetingC++ 2018 Talk](https://naios.github.io/talks/2018-11-17-Meeting-C%2B%2B-Berlin/Continuable.pdf) |
|
|
||||||
| :---: |
|
|
||||||
| [<img alt="Continuable MeetingC++" width="60%" src="https://img.youtube.com/vi/l6-spMA_x6g/0.jpg">](https://www.youtube.com/watch?v=l6-spMA_x6g)] |
|
|
||||||
|
|
||||||
.
|
|
||||||
|
|||||||
34
appveyor.yml
34
appveyor.yml
@ -1,17 +1,17 @@
|
|||||||
image:
|
image:
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
- Visual Studio 2019
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- WITH_NO_EXCEPTIONS: OFF
|
- WITH_NO_EXCEPTIONS: OFF
|
||||||
WITH_CPP_LATEST: OFF
|
WITH_CPP_LATEST: OFF
|
||||||
- WITH_NO_EXCEPTIONS: ON
|
- WITH_NO_EXCEPTIONS: ON
|
||||||
WITH_CPP_LATEST: OFF
|
WITH_CPP_LATEST: OFF
|
||||||
- WITH_NO_EXCEPTIONS: OFF
|
- WITH_NO_EXCEPTIONS: OFF
|
||||||
WITH_CPP_LATEST: ON
|
WITH_CPP_LATEST: ON
|
||||||
- WITH_NO_EXCEPTIONS: ON
|
|
||||||
WITH_CPP_LATEST: ON
|
configuration:
|
||||||
|
- Debug
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
- x64
|
- x64
|
||||||
@ -24,20 +24,18 @@ clone_script:
|
|||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: >
|
- cmd: >
|
||||||
cmake -H. -Bbuild -A%PLATFORM%
|
cmake -H. -Bbuild -A%PLATFORM%
|
||||||
-DCTI_CONTINUABLE_WITH_NO_EXCEPTIONS=%WITH_NO_EXCEPTIONS%
|
-DCTI_CONTINUABLE_WITH_NO_EXCEPTIONS=%WITH_NO_EXCEPTIONS%
|
||||||
-DCTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE=ON
|
-DCTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE=ON
|
||||||
-DCTI_CONTINUABLE_WITH_CPP_LATEST=%WITH_CPP_LATEST%
|
-DCTI_CONTINUABLE_WITH_CPP_LATEST=%WITH_CPP_LATEST%
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: cmake --build build --config Debug --target ALL_BUILD -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:minimal /maxcpucount:2 /nologo
|
- cmd: cmake --build build --config %CONFIGURATION% --target ALL_BUILD -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:minimal /maxcpucount:2 /nologo
|
||||||
- cmd: cmake --build build --config Debug --target ALL_BUILD -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:minimal /maxcpucount:2 /nologo
|
- cmd: cmake --build build --config %CONFIGURATION% --target PACKAGE -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:minimal /maxcpucount:2 /nologo
|
||||||
- cmd: cmake --build build --config Release --target PACKAGE -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:minimal /maxcpucount:2 /nologo
|
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- cmd: cd build
|
- cmd: cd build
|
||||||
- cmd: ctest -C Debug -V .
|
- cmd: ctest -C %CONFIGURATION% -V .
|
||||||
- cmd: ctest -C Release -V .
|
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: 'build/*.zip'
|
- path: 'build/*.zip'
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -31,18 +31,9 @@ if (PLATFORM EQUAL 64)
|
|||||||
-D_WIN64)
|
-D_WIN64)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CTI_CONTINUABLE_WITH_CONCURRENT_JOBS)
|
|
||||||
target_compile_options(continuable-features-flags
|
|
||||||
INTERFACE
|
|
||||||
/MP${CTI_CONTINUABLE_WITH_CONCURRENT_JOBS})
|
|
||||||
else()
|
|
||||||
target_compile_options(continuable-features-flags
|
|
||||||
INTERFACE
|
|
||||||
/MP)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_options(continuable-features-flags
|
target_compile_options(continuable-features-flags
|
||||||
INTERFACE
|
INTERFACE
|
||||||
|
/MP
|
||||||
/bigobj
|
/bigobj
|
||||||
/permissive-)
|
/permissive-)
|
||||||
|
|
||||||
@ -50,7 +41,11 @@ target_compile_options(continuable-features-warnings
|
|||||||
INTERFACE
|
INTERFACE
|
||||||
/W4)
|
/W4)
|
||||||
|
|
||||||
if (NOT CTI_CONTINUABLE_WITH_CPP_LATEST)
|
if (CTI_CONTINUABLE_WITH_CPP_LATEST)
|
||||||
|
target_compile_options(continuable-features-flags
|
||||||
|
INTERFACE
|
||||||
|
/std:c++latest)
|
||||||
|
else()
|
||||||
target_compile_options(continuable-features-flags
|
target_compile_options(continuable-features-flags
|
||||||
INTERFACE
|
INTERFACE
|
||||||
/std:c++14)
|
/std:c++14)
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
|
|
||||||
|
|
||||||
@PACKAGE_INIT@
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
|
||||||
|
|
||||||
check_required_components(@PROJECT_NAME@)
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
# Select the compiler specific cmake file
|
# Select the compiler specific cmake file
|
||||||
set(MSVC_ID "MSVC")
|
set(MSVC_ID "MSVC")
|
||||||
if (${CMAKE_CXX_COMPILER_ID} MATCHES "(Apple)?Clang")
|
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||||
include(${PROJECT_SOURCE_DIR}/cmake/compiler/clang.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/compiler/clang.cmake)
|
||||||
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||||
include(${PROJECT_SOURCE_DIR}/cmake/compiler/gcc.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/compiler/gcc.cmake)
|
||||||
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL ${MSVC_ID})
|
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL ${MSVC_ID})
|
||||||
include(${PROJECT_SOURCE_DIR}/cmake/compiler/msvc.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/compiler/msvc.cmake)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unknown compiler!")
|
message(FATAL_ERROR "Unknown compiler!")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,10 +13,10 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
include(${PROJECT_SOURCE_DIR}/cmake/macros/group_sources.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/macros/group_sources.cmake)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
# Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files(the "Software"), to deal
|
# of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,48 +13,46 @@
|
|||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
set(WITH_SOURCE_TREE "hierarchical")
|
set(WITH_SOURCE_TREE "hierarchical")
|
||||||
macro(group_sources)
|
macro(group_sources dir)
|
||||||
# Skip this if WITH_SOURCE_TREE is not set (empty string).
|
# Skip this if WITH_SOURCE_TREE is not set (empty string).
|
||||||
if (NOT ${WITH_SOURCE_TREE} STREQUAL "")
|
if (NOT ${WITH_SOURCE_TREE} STREQUAL "")
|
||||||
foreach(dir ${ARGN})
|
# Include all header and c files
|
||||||
# Include all header and c files
|
file(GLOB_RECURSE elements RELATIVE ${dir} *.h *.hpp *.inl *.inc *.c *.cpp *.cc)
|
||||||
file(GLOB_RECURSE elements RELATIVE ${dir} ${dir}/*)
|
|
||||||
|
|
||||||
foreach(element ${elements})
|
foreach(element ${elements})
|
||||||
# Extract filename and directory
|
# Extract filename and directory
|
||||||
get_filename_component(element_name ${element} NAME)
|
get_filename_component(element_name ${element} NAME)
|
||||||
get_filename_component(element_dir ${element} DIRECTORY)
|
get_filename_component(element_dir ${element} DIRECTORY)
|
||||||
|
|
||||||
if (NOT ${element_dir} STREQUAL "")
|
if (NOT ${element_dir} STREQUAL "")
|
||||||
# If the file is in a subdirectory use it as source group.
|
# If the file is in a subdirectory use it as source group.
|
||||||
if (${WITH_SOURCE_TREE} STREQUAL "flat")
|
if (${WITH_SOURCE_TREE} STREQUAL "flat")
|
||||||
# Build flat structure by using only the first subdirectory.
|
# Build flat structure by using only the first subdirectory.
|
||||||
string(FIND ${element_dir} "/" delemiter_pos)
|
string(FIND ${element_dir} "/" delemiter_pos)
|
||||||
if (NOT ${delemiter_pos} EQUAL -1)
|
if (NOT ${delemiter_pos} EQUAL -1)
|
||||||
string(SUBSTRING ${element_dir} 0 ${delemiter_pos} group_name)
|
string(SUBSTRING ${element_dir} 0 ${delemiter_pos} group_name)
|
||||||
source_group("${group_name}" FILES ${dir}/${element})
|
|
||||||
else()
|
|
||||||
# Build hierarchical structure.
|
|
||||||
# File is in root directory.
|
|
||||||
source_group("${element_dir}" FILES ${dir}/${element})
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# Use the full hierarchical structure to build source_groups.
|
|
||||||
string(REPLACE "/" "\\" group_name ${element_dir})
|
|
||||||
source_group("${group_name}" FILES ${dir}/${element})
|
source_group("${group_name}" FILES ${dir}/${element})
|
||||||
|
else()
|
||||||
|
# Build hierarchical structure.
|
||||||
|
# File is in root directory.
|
||||||
|
source_group("${element_dir}" FILES ${dir}/${element})
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# If the file is in the root directory, place it in the root source_group.
|
# Use the full hierarchical structure to build source_groups.
|
||||||
source_group("\\" FILES ${dir}/${element})
|
string(REPLACE "/" "\\" group_name ${element_dir})
|
||||||
|
source_group("${group_name}" FILES ${dir}/${element})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
else()
|
||||||
|
# If the file is in the root directory, place it in the root source_group.
|
||||||
|
source_group("\\" FILES ${dir}/${element})
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|||||||
37
conanfile.py
37
conanfile.py
@ -1,37 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from conans import ConanFile, tools
|
|
||||||
|
|
||||||
def get_version():
|
|
||||||
git = tools.Git()
|
|
||||||
try:
|
|
||||||
return git.run("describe --tags --abbrev=0")
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
class ContinuableConan(ConanFile):
|
|
||||||
name = "continuable"
|
|
||||||
version = get_version()
|
|
||||||
license = "MIT"
|
|
||||||
url = "https://github.com/Naios/continuable"
|
|
||||||
author = "Denis Blank (denis.blank@outlook.com)"
|
|
||||||
description = "C++14 asynchronous allocation aware futures"
|
|
||||||
homepage = "https://naios.github.io/continuable/"
|
|
||||||
no_copy_source = True
|
|
||||||
scm = {
|
|
||||||
"type": "git",
|
|
||||||
"url": "auto",
|
|
||||||
"revision": "auto"
|
|
||||||
}
|
|
||||||
|
|
||||||
def package(self):
|
|
||||||
self.copy("LICENSE.txt", "licenses")
|
|
||||||
self.copy("include/*.hpp")
|
|
||||||
self.copy("include/*.inl")
|
|
||||||
|
|
||||||
def package_id(self):
|
|
||||||
self.info.header_only()
|
|
||||||
|
|
||||||
def requirements(self):
|
|
||||||
self.requires("function2/4.0.0@naios/stable")
|
|
||||||
@ -1,25 +1,13 @@
|
|||||||
if(NOT TARGET function2::function2)
|
if(NOT TARGET function2)
|
||||||
add_subdirectory(function2)
|
add_subdirectory(function2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CTI_CONTINUABLE_WITH_TESTS OR CTI_CONTINUABLE_WITH_BENCHMARKS)
|
if (CTI_CONTINUABLE_WITH_TESTS OR CTI_CONTINUABLE_WITH_EXAMPLES)
|
||||||
if(NOT TARGET gtest)
|
if(NOT TARGET gtest)
|
||||||
add_subdirectory(googletest)
|
add_subdirectory(googletest)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CTI_CONTINUABLE_WITH_EXAMPLES)
|
|
||||||
if(NOT TARGET asio)
|
if(NOT TARGET asio)
|
||||||
add_subdirectory(asio)
|
add_subdirectory(asio)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CTI_CONTINUABLE_WITH_BENCHMARKS)
|
|
||||||
if(NOT TARGET benchmark)
|
|
||||||
add_subdirectory(benchmark)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT TARGET boost)
|
|
||||||
add_subdirectory(boost)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
add_library(asio STATIC
|
add_library(asio STATIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}/asio/asio/src/asio.cpp
|
${CMAKE_CURRENT_LIST_DIR}/asio/asio/src/asio.cpp)
|
||||||
${CMAKE_CURRENT_LIST_DIR}/include/boost/throw_exception.hpp)
|
|
||||||
|
|
||||||
target_include_directories(asio
|
target_include_directories(asio
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}/asio/asio/include
|
${CMAKE_CURRENT_LIST_DIR}/asio/asio/include)
|
||||||
${CMAKE_CURRENT_LIST_DIR}/include)
|
|
||||||
|
|
||||||
target_compile_definitions(asio
|
target_compile_definitions(asio
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@ -13,15 +11,6 @@ target_compile_definitions(asio
|
|||||||
-DASIO_SEPARATE_COMPILATION=1
|
-DASIO_SEPARATE_COMPILATION=1
|
||||||
-DASIO_NO_TYPEID=1)
|
-DASIO_NO_TYPEID=1)
|
||||||
|
|
||||||
if (CTI_CONTINUABLE_WITH_NO_EXCEPTIONS)
|
|
||||||
target_compile_definitions(asio
|
|
||||||
PUBLIC
|
|
||||||
-DASIO_NO_EXCEPTIONS=1
|
|
||||||
-DASIO_HAS_BOOST_THROW_EXCEPTION=1)
|
|
||||||
|
|
||||||
message(STATUS "ASIO: Disabled exceptions")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_compile_definitions(asio
|
target_compile_definitions(asio
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 6c054e98f3f53352d12b6cd46d63b6d404cc044b
|
Subproject commit 230c0d2ae035c5ce1292233fcab03cea0d341264
|
||||||
@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.0.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
|
||||||
|
|
||||||
#if defined(ASIO_STANDALONE) && defined(ASIO_NO_EXCEPTIONS)
|
|
||||||
# include <cstdio>
|
|
||||||
# include <cstdlib>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
template <typename Exception>
|
|
||||||
void throw_exception(Exception const& e) {
|
|
||||||
puts(e.what());
|
|
||||||
std::abort();
|
|
||||||
}
|
|
||||||
} // namespace boost
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
set(BENCHMARK_ENABLE_TESTING OFF)
|
|
||||||
if (CTI_CONTINUABLE_WITHOUT_EXCEPTIONS)
|
|
||||||
set(BENCHMARK_ENABLE_EXCEPTIONS OFF)
|
|
||||||
else()
|
|
||||||
set(BENCHMARK_ENABLE_EXCEPTIONS ON)
|
|
||||||
endif()
|
|
||||||
set(BENCHMARK_ENABLE_INSTALL OFF)
|
|
||||||
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
|
|
||||||
add_subdirectory(benchmark)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Subproject commit b874e72208b6e21b62287942e5e3b11f6630107f
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
if(WIN32)
|
|
||||||
if(CMAKE_SIZEOF_VOID_P MATCHES 8)
|
|
||||||
set(PLATFORM 64)
|
|
||||||
else()
|
|
||||||
set(PLATFORM 32)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED ENV{BOOST_ROOT})
|
|
||||||
set(BOOST_ROOT $ENV{BOOST_ROOT})
|
|
||||||
set(BOOST_LIBRARYDIR ${BOOST_ROOT}/lib${PLATFORM}-msvc-14.1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
|
||||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(Boost 1.68 REQUIRED
|
|
||||||
COMPONENTS
|
|
||||||
system
|
|
||||||
iostreams
|
|
||||||
thread)
|
|
||||||
|
|
||||||
if (${Boost_FOUND})
|
|
||||||
add_library(boost INTERFACE)
|
|
||||||
|
|
||||||
target_link_libraries(boost
|
|
||||||
INTERFACE
|
|
||||||
Boost::system
|
|
||||||
Boost::iostreams
|
|
||||||
Boost::thread)
|
|
||||||
|
|
||||||
target_compile_definitions(boost
|
|
||||||
INTERFACE
|
|
||||||
BOOST_ALL_NO_LIB
|
|
||||||
BOOST_ASIO_DISABLE_BOOST_DATE_TIME
|
|
||||||
BOOST_ASIO_DISABLE_BOOST_REGEX
|
|
||||||
BOOST_RANGE_ENABLE_CONCEPT_ASSERT=0
|
|
||||||
BOOST_THREAD_PROVIDES_FUTURE
|
|
||||||
BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
|
||||||
BOOST_FILESYSTEM_NO_DEPRECATED
|
|
||||||
BOOST_THREAD_VERSION=4)
|
|
||||||
endif()
|
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 3a0746bf5f601dfed05330aefcb6854354fce07d
|
Subproject commit db03b55bc9b58999b1e653a1d57fe1056fe14778
|
||||||
@ -1,4 +1,3 @@
|
|||||||
if(ON)
|
|
||||||
add_library(gtest STATIC
|
add_library(gtest STATIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}/googletest/googletest/src/gtest-all.cc)
|
${CMAKE_CURRENT_LIST_DIR}/googletest/googletest/src/gtest-all.cc)
|
||||||
|
|
||||||
@ -43,10 +42,3 @@ target_include_directories(gmock
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/googletest/googlemock
|
${CMAKE_CURRENT_LIST_DIR}/googletest/googlemock
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}/googletest/googlemock/include)
|
${CMAKE_CURRENT_LIST_DIR}/googletest/googlemock/include)
|
||||||
|
|
||||||
else()
|
|
||||||
set(BUILD_GTEST ON)
|
|
||||||
set(BUILD_GMOCK OFF)
|
|
||||||
set(INSTALL_GTEST OFF)
|
|
||||||
add_subdirectory(googletest)
|
|
||||||
endif()
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit f2fb48c3b3d79a75a88a99fba6576b25d42ec528
|
Subproject commit 9bda90b7e5e08c4c37a832d0cea218aed6af6470
|
||||||
@ -38,13 +38,13 @@ PROJECT_NAME = Continuable
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 4.1.0
|
PROJECT_NUMBER = 3.0.0
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
# quick idea about the purpose of the project. Keep the description short.
|
# quick idea about the purpose of the project. Keep the description short.
|
||||||
|
|
||||||
PROJECT_BRIEF = "C++14 asynchronous allocation aware futures"
|
PROJECT_BRIEF =
|
||||||
|
|
||||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||||
# in the documentation. The maximum height of the logo should not exceed 55
|
# in the documentation. The maximum height of the logo should not exceed 55
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -28,146 +28,20 @@ namespace cti {
|
|||||||
|
|
||||||
Following versions were released:
|
Following versions were released:
|
||||||
|
|
||||||
\subsection changelog-versions-4-0-0 4.0.0
|
|
||||||
|
|
||||||
Various issues have been resolved:
|
|
||||||
|
|
||||||
- [#27: First class, zero-overhead ASIO integration](https://github.com/Naios/continuable/issues/27)
|
|
||||||
- [#23: VS 16.2: parameter pack must be expanded in this context](https://github.com/Naios/continuable/issues/23)
|
|
||||||
- [#21: Infinite recursion during compilation](https://github.com/Naios/continuable/issues/21)
|
|
||||||
- [#16: Add AppleClang compiler to cmake](https://github.com/Naios/continuable/issues/16)
|
|
||||||
- [#13: unit-test/test-continuable-single fails on gcc 8.2](https://github.com/Naios/continuable/issues/13)
|
|
||||||
- [#11: Forward declarations are no longer allowed in type-erased continuables](https://github.com/Naios/continuable/issues/11)
|
|
||||||
|
|
||||||
Following methods and functions have been added:
|
|
||||||
|
|
||||||
<B>Various improvements to continuable_base:</B>
|
|
||||||
|
|
||||||
- \ref continuable_base::as for casting to a continuable_base with different arguments
|
|
||||||
- \ref continuable_base::finish for 'materializing' an intermediate chained continuable_base
|
|
||||||
|
|
||||||
<B>An asychronous initiation function comparable to std::async:</B>
|
|
||||||
|
|
||||||
The asynchronous facilities make it possible now to start with a handler
|
|
||||||
instead of a continuation:
|
|
||||||
|
|
||||||
\code{.cpp}
|
|
||||||
async([] {
|
|
||||||
// ...
|
|
||||||
}).then(...);
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
- \ref async Makes it possible to start with a handler instead of a continuation, comparable to `std::async`
|
|
||||||
- \ref async_on allows to specify an additional executor parameter
|
|
||||||
|
|
||||||
<B>The result class and modifying the asynchronous control flow</B>
|
|
||||||
|
|
||||||
Every continuation handler used in \ref continuable_base::then, \ref continuable_base::next
|
|
||||||
and \ref continuable_base::fail allows now to return a \ref result which represents
|
|
||||||
the asynchronous result.
|
|
||||||
|
|
||||||
This allows recovering from failures or throwing of exception types from
|
|
||||||
handlers when exceptions are disabled.
|
|
||||||
|
|
||||||
Result handling and
|
|
||||||
- \ref result
|
|
||||||
- \ref rethrow Throws an exception or error code from a result or failure handler
|
|
||||||
- \ref cancel Throws a default constructed exception type or error code from a result or failure handler to signal cancellation.
|
|
||||||
- \ref stop \copybrief stop
|
|
||||||
- \ref make_result \copybrief make_result
|
|
||||||
|
|
||||||
Special result types
|
|
||||||
- \ref empty_result \copybrief empty_result
|
|
||||||
- \ref cancellation_result \copybrief cancellation_result
|
|
||||||
- \ref exceptional_result \copybrief exceptional_result
|
|
||||||
|
|
||||||
<B>Optimize 'ready' continuables:</B>
|
|
||||||
|
|
||||||
Continuables which are 'ready' and side effect free can now be unpacked
|
|
||||||
synchronously. Mainly such continuables are created through \ref make_ready_continuable,
|
|
||||||
\ref make_exceptional_continuable and \ref make_cancelling_continuable.
|
|
||||||
|
|
||||||
- \ref continuable_base::is_ready \copybrief continuable_base::is_ready
|
|
||||||
- \ref continuable_base::unpack \copybrief continuable_base::unpack
|
|
||||||
- \ref make_cancelling_continuable \copybrief make_cancelling_continuable
|
|
||||||
|
|
||||||
Including various helper tags for the underlying changed continuation object structure:
|
|
||||||
|
|
||||||
- \ref signature_arg_t
|
|
||||||
- \ref is_ready_arg_t
|
|
||||||
- \ref unpack_arg_t
|
|
||||||
- \ref exception_arg_t
|
|
||||||
- \ref exception_t
|
|
||||||
|
|
||||||
<B>asio asynchronous initiate token:</B>
|
|
||||||
|
|
||||||
The \ref use_continuable_t special tag can be used to make (boost) asio
|
|
||||||
return a \ref continuable_base.
|
|
||||||
|
|
||||||
- \ref use_continuable \copybrief use_continuable_t
|
|
||||||
|
|
||||||
\code{.cpp}
|
|
||||||
#include <continuable/continuable.hpp>
|
|
||||||
#include <continuable/external/asio.hpp>
|
|
||||||
#include <asio.hpp>
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
asio::tcp::resolver resolver(...);
|
|
||||||
resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
|
|
||||||
.then([](asio::udp::resolver::iterator iterator) {
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
<B>Iterating over an asynchronous control flow:</B>
|
|
||||||
|
|
||||||
The loop function was added which makes is possible to emulate an asynchronous loop,
|
|
||||||
that is comparable to a `co_await` with `for`.
|
|
||||||
|
|
||||||
- \ref loop \copybrief loop
|
|
||||||
- \ref loop_result \copybrief loop_result
|
|
||||||
- \ref loop_break \copybrief loop_break
|
|
||||||
- \ref loop_continue \copybrief loop_continue
|
|
||||||
- \ref range_loop \copybrief range_loop
|
|
||||||
- \ref range_loop \copybrief range_loop
|
|
||||||
- \ref plain_t \copybrief plain_t
|
|
||||||
- \ref make_plain \copybrief make_plain
|
|
||||||
|
|
||||||
<B>Synchronous wait transforms:</B>
|
|
||||||
|
|
||||||
The wait transforms allows to block the current thread until a \ref continuable_base
|
|
||||||
was resolved.
|
|
||||||
|
|
||||||
- \ref transforms::wait \copybrief transforms::wait
|
|
||||||
- \ref transforms::wait_for Same as \ref transforms::wait wich waits for a given duration
|
|
||||||
- \ref transforms::wait_until Same as \ref transforms::wait wich waits until a given timepoint
|
|
||||||
|
|
||||||
<B>Various changes:</B>
|
|
||||||
|
|
||||||
Many more unlisted changes including:
|
|
||||||
|
|
||||||
- \ref work \copybrief work
|
|
||||||
- \ref continuation_capacity
|
|
||||||
- \ref promisify::with \copybrief promisify::with
|
|
||||||
- \ref void_arg_t
|
|
||||||
|
|
||||||
Additional various bugfixes have been made.
|
|
||||||
|
|
||||||
\subsection changelog-versions-3-0-0 3.0.0
|
\subsection changelog-versions-3-0-0 3.0.0
|
||||||
|
|
||||||
<B>New helper functions</B>
|
<B>New helper functions</B>
|
||||||
|
|
||||||
New helper functions were added to create ready continuables:
|
New helper functions were added to create ready continuables:
|
||||||
|
|
||||||
- \ref make_ready_continuable \copybrief make_ready_continuable
|
- \ref make_ready_continuable
|
||||||
- \ref make_exceptional_continuable \copybrief make_exceptional_continuable
|
- \ref make_exceptional_continuable
|
||||||
|
|
||||||
<B>Improvements to connections</B>
|
<B>Improvements to connections</B>
|
||||||
|
|
||||||
The implementation of connections were rewritten entirely.
|
The implementation of connections were rewritten entirely.
|
||||||
It is possible now to connect runtime sized containers as well as
|
It is possible now to connect runtime sized containers as well as
|
||||||
deeply nested sequences. See \ref tutorial-connecting-continuables for details.
|
deeply nested sequences. See \ref tutorial-connections for details.
|
||||||
|
|
||||||
Additionally connection overloads were added that accept two iterators
|
Additionally connection overloads were added that accept two iterators
|
||||||
in order to come closer to the interface of the standard library.
|
in order to come closer to the interface of the standard library.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -33,8 +33,6 @@ in order to change the libraries behaviour:
|
|||||||
| `CONTINUABLE_WITH_NO_EXCEPTIONS` | Exceptions are disabled and `std::error_condition` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
| `CONTINUABLE_WITH_NO_EXCEPTIONS` | Exceptions are disabled and `std::error_condition` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
||||||
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
||||||
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
|
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
|
||||||
| `CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK` | Allows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers. |
|
|
||||||
| `CONTINUABLE_WITH_IMMEDIATE_TYPES` | Don't decorate the used type erasure, which is done to keep type names minimal for better error messages in debug builds. |
|
|
||||||
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
|
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -76,7 +76,7 @@ your personal experience in using the library to improve it.
|
|||||||
Continuable is licensed under the MIT license:
|
Continuable is licensed under the MIT license:
|
||||||
|
|
||||||
>
|
>
|
||||||
> Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
> Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
>
|
>
|
||||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
> of this software and associated documentation files(the "Software"), to deal
|
> of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -90,7 +90,7 @@ Continuable is licensed under the MIT license:
|
|||||||
>
|
>
|
||||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -49,7 +49,7 @@ Continuable is a header-only library with one required header-only dependency:
|
|||||||
erasure wrapper to convert a \ref continuable_base into a \ref continuable.
|
erasure wrapper to convert a \ref continuable_base into a \ref continuable.
|
||||||
|
|
||||||
Additionally GTest is required as optional dependency for the asynchronous
|
Additionally GTest is required as optional dependency for the asynchronous
|
||||||
unit testing macros defined in `continuable/support/gtest.hpp`
|
unit testing macros defined in `continuable/continuable-testing.hpp`
|
||||||
if those are used:
|
if those are used:
|
||||||
|
|
||||||
- [google/googletest](https://github.com/google/googletest) is used as
|
- [google/googletest](https://github.com/google/googletest) is used as
|
||||||
@ -120,14 +120,6 @@ and might be installed from there.
|
|||||||
to make it available from various package managers in order to
|
to make it available from various package managers in order to
|
||||||
make the installation easier.
|
make the installation easier.
|
||||||
|
|
||||||
\subsection installation-installation-amalgamation By using the amalgamation header
|
|
||||||
|
|
||||||
For major versions there is an amalgamation header provided which can be
|
|
||||||
included without any dependency:
|
|
||||||
|
|
||||||
- [4.0.0](https://gist.githubusercontent.com/Naios/25d731aa4707d35a9bcec507f3cb9038/raw/051d2ea07b6704893c7fc9844e8d1c105c6821e0/continuable.hpp)
|
|
||||||
- [3.0.0](https://gist.githubusercontent.com/Naios/b128ab5028a7eb33e4285c0293573d9f/raw/79fe332964a786b21a8661ef65d07a5669260a3c/continuable.hpp)
|
|
||||||
|
|
||||||
\subsection installation-installation-copy By copying the headers
|
\subsection installation-installation-copy By copying the headers
|
||||||
|
|
||||||
If you don't want to rely on CMake or package managers it is possible to
|
If you don't want to rely on CMake or package managers it is possible to
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -96,34 +96,16 @@ result.get_value();
|
|||||||
result.get_exception();
|
result.get_exception();
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\section tutorial-awaiting-continuables-return Using continuables as return type from coroutines
|
|
||||||
|
|
||||||
It is possible to use a \ref continuable_base as return type from coroutines.
|
|
||||||
|
|
||||||
|
\note It isn't possible as of now to use a \ref continuable_base
|
||||||
|
as return type from coroutines:
|
||||||
\code{.cpp}
|
\code{.cpp}
|
||||||
cti::continuable<> resolve_async_void() {
|
cti::continuable<int> do_sth() {
|
||||||
co_await http_request("github.com");
|
|
||||||
// ...
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cti::continuable<int> resolve_async() {
|
|
||||||
co_await http_request("github.com");
|
co_await http_request("github.com");
|
||||||
// ...
|
// ...
|
||||||
co_return 0;
|
co_return 0;
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Additionally it's possible to return multiple return values from coroutines
|
|
||||||
by wrapping those in a tuple like type:
|
|
||||||
|
|
||||||
\code{.cpp}
|
|
||||||
cti::continuable<int, int, int> resolve_async_multiple() {
|
|
||||||
co_await http_request("github.com");
|
|
||||||
// ...
|
|
||||||
co_return std::make_tuple(0, 1, 2);
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -202,7 +202,7 @@ for (int i = 2; i < 5; ++i) {
|
|||||||
container.emplace_back(cti::make_ready_continuable(i));
|
container.emplace_back(cti::make_ready_continuable(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
cti::when_all(std::move(v))
|
cti::when_all(v)
|
||||||
.then([](std::vector<int> resolved) {
|
.then([](std::vector<int> resolved) {
|
||||||
// ...
|
// ...
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -70,30 +70,5 @@ async_resolve("127.0.0.1", "daytime")
|
|||||||
});
|
});
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
\section tutorial-promisify-continuables-boost-ct asio and boost::asio async completion tokens
|
|
||||||
|
|
||||||
Since version 4.0.0 continuable also supports asio async initiation tokens.
|
|
||||||
|
|
||||||
- Boost 1.70 or asio 1.13.0 is required for the async initiation
|
|
||||||
- Until boost 1.72 or asio 1.16.0 overhead through an additional type
|
|
||||||
erasure is added. It is recommended to update to those versions.
|
|
||||||
|
|
||||||
The special static variable \ref cti::use_continuable can be appended to any
|
|
||||||
(boost) asio function that accepts a callback to make it return a \ref continuable_base.
|
|
||||||
|
|
||||||
\code{.cpp}
|
|
||||||
#include <continuable/continuable.hpp>
|
|
||||||
#include <continuable/external/asio.hpp>
|
|
||||||
#include <asio.hpp>
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
asio::tcp::resolver resolver(...);
|
|
||||||
resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
|
|
||||||
.then([](asio::udp::resolver::iterator iterator) {
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
\endcode
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -30,37 +30,28 @@ namespace cti {
|
|||||||
|
|
||||||
Sometimes it's required to change a \ref continuable_base object by its whole.
|
Sometimes it's required to change a \ref continuable_base object by its whole.
|
||||||
Thus the library offers the ability to apply a transformation to any
|
Thus the library offers the ability to apply a transformation to any
|
||||||
\ref continuable_base through using \link continuable_base::apply apply \endlink.
|
\ref continuable_base through using \link continuable_base::apply apply \endlink
|
||||||
|
or \link continuable_base::operator | its operator | \endlink.
|
||||||
|
|
||||||
A transformation is a callable object that accepts a \ref continuable_base
|
A transformation accepts a \ref continuable_base and returns
|
||||||
and returns an arbitrary object
|
an arbitrary object.
|
||||||
|
|
||||||
|
To create a transformation use the \ref make_transform function:
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
auto transform = cti::make_transform([] (auto&& continuable) {
|
||||||
|
// Change the continuable
|
||||||
|
return std::forward<decltype(continuable)>(continuable);
|
||||||
|
});
|
||||||
|
\endcode
|
||||||
|
|
||||||
The library provides several transforms already as part of the
|
The library provides several transforms already as part of the
|
||||||
\ref cti::transforms namespace.
|
\ref cti::transforms namespace.
|
||||||
|
|
||||||
\section tutorial-transforming-continuables-wait Synchronous wait
|
|
||||||
|
|
||||||
The library is capable of converting every asynchronous control flow
|
|
||||||
into a synchronous one through \ref transforms::wait, \ref transforms::wait_for
|
|
||||||
and \ref transforms::wait_until.
|
|
||||||
|
|
||||||
\code{.cpp}
|
|
||||||
std::string response = http_request("github.com")
|
|
||||||
.apply(cti::transforms::wait());
|
|
||||||
|
|
||||||
std::string response = http_request("github.com")
|
|
||||||
.apply(cti::transforms::wait_for(std::chrono::seconds(5)));
|
|
||||||
|
|
||||||
std::string response = http_request("github.com")
|
|
||||||
.apply(cti::transforms::wait_until(...));
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
The current thread will be blocked until the result has arrived
|
|
||||||
|
|
||||||
\section tutorial-transforming-continuables-future Conversion into std::future
|
\section tutorial-transforming-continuables-future Conversion into std::future
|
||||||
|
|
||||||
The library is capable of converting (*futurizing*) every continuable into a
|
The library is capable of converting (*futurizing*) every continuable into a
|
||||||
fitting `std::future` through the \ref transforms::to_future transform:
|
fitting `std::future` through the \ref transforms::futurize transform:
|
||||||
|
|
||||||
\code{.cpp}
|
\code{.cpp}
|
||||||
std::future<std::string> future = http_request("github.com")
|
std::future<std::string> future = http_request("github.com")
|
||||||
@ -68,17 +59,17 @@ std::future<std::string> future = http_request("github.com")
|
|||||||
// Do sth...
|
// Do sth...
|
||||||
return http_request("travis-ci.org") || http_request("atom.io");
|
return http_request("travis-ci.org") || http_request("atom.io");
|
||||||
})
|
})
|
||||||
.apply(cti::transforms::to_future());
|
.apply(cti::transforms::futurize());
|
||||||
// ^^^^^^^^
|
// ^^^^^^^^
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Multiple arguments which can't be handled by `std::future` itself are
|
Multiple arguments which can't be handled by `std::future` itself are
|
||||||
converted into `std::tuple`, see \ref transforms::to_future for details.
|
converted into `std::tuple`, see \ref transforms::futurize for details.
|
||||||
|
|
||||||
\code{.cpp}
|
\code{.cpp}
|
||||||
std::future<std::tuple<std::string, std::string>> future =
|
std::future<std::tuple<std::string, std::string>> future =
|
||||||
(http_request("travis-ci.org") && http_request("atom.io"))
|
(http_request("travis-ci.org") && http_request("atom.io"))
|
||||||
.apply(cti::transforms::to_future());
|
.apply(cti::transforms::futurize());
|
||||||
\endcode
|
\endcode
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v3.0.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -1,28 +1,15 @@
|
|||||||
add_library(asio-example-deps INTERFACE)
|
|
||||||
|
|
||||||
target_include_directories(asio-example-deps
|
|
||||||
INTERFACE
|
|
||||||
${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
target_link_libraries(asio-example-deps
|
|
||||||
INTERFACE
|
|
||||||
asio
|
|
||||||
continuable)
|
|
||||||
|
|
||||||
add_executable(example-asio
|
add_executable(example-asio
|
||||||
${CMAKE_CURRENT_LIST_DIR}/example-asio.cpp)
|
${CMAKE_CURRENT_LIST_DIR}/example-asio.cpp)
|
||||||
|
|
||||||
|
target_include_directories(example-asio
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
target_link_libraries(example-asio
|
target_link_libraries(example-asio
|
||||||
PRIVATE
|
PRIVATE
|
||||||
asio-example-deps)
|
asio
|
||||||
|
continuable)
|
||||||
|
|
||||||
target_compile_definitions(example-asio
|
target_compile_definitions(example-asio
|
||||||
PUBLIC
|
PUBLIC
|
||||||
-DCONTINUABLE_WITH_NO_EXCEPTIONS)
|
-DCONTINUABLE_WITH_NO_EXCEPTIONS)
|
||||||
|
|
||||||
add_executable(example-asio-integration
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/example-asio-integration.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(example-asio-integration
|
|
||||||
PRIVATE
|
|
||||||
asio-example-deps)
|
|
||||||
|
|||||||
@ -1,176 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.0.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <asio.hpp>
|
|
||||||
|
|
||||||
#include <continuable/continuable.hpp>
|
|
||||||
#include <continuable/external/asio.hpp>
|
|
||||||
|
|
||||||
// Queries the NIST daytime service and prints the current date and time
|
|
||||||
void daytime_service();
|
|
||||||
|
|
||||||
// Checks that a timer async_wait returns successfully
|
|
||||||
void successful_async_wait();
|
|
||||||
|
|
||||||
// Checks that a cancelled timer async_wait fails with
|
|
||||||
// `asio::error::operation_aborted` and is converted to a default constructed
|
|
||||||
// cti::exception_t.
|
|
||||||
void cancelled_async_wait();
|
|
||||||
|
|
||||||
// Indicates fatal error due to an unexpected failure in the continuation chain.
|
|
||||||
void unexpected_error(cti::exception_t);
|
|
||||||
|
|
||||||
// Check that the failure was an aborted operation, as expected.
|
|
||||||
void check_aborted_operation(cti::exception_t);
|
|
||||||
|
|
||||||
// Use a strand as executor
|
|
||||||
void using_strand();
|
|
||||||
|
|
||||||
int main(int, char**) {
|
|
||||||
daytime_service();
|
|
||||||
|
|
||||||
successful_async_wait();
|
|
||||||
cancelled_async_wait();
|
|
||||||
|
|
||||||
using_strand();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void daytime_service() {
|
|
||||||
using asio::ip::tcp;
|
|
||||||
asio::io_context ioc(1);
|
|
||||||
tcp::resolver resolver(ioc);
|
|
||||||
tcp::socket socket(ioc);
|
|
||||||
std::string buf;
|
|
||||||
|
|
||||||
resolver.async_resolve("time.nist.gov", "daytime", cti::use_continuable)
|
|
||||||
.then([&socket](tcp::resolver::results_type endpoints) {
|
|
||||||
return asio::async_connect(socket, endpoints, cti::use_continuable);
|
|
||||||
})
|
|
||||||
.then([&socket, &buf] {
|
|
||||||
return asio::async_read_until(socket, asio::dynamic_buffer(buf), '\n',
|
|
||||||
cti::use_continuable);
|
|
||||||
})
|
|
||||||
.then([&buf](std::size_t) {
|
|
||||||
puts("Continuation successfully got a daytime response:");
|
|
||||||
puts(buf.c_str());
|
|
||||||
})
|
|
||||||
.fail(&unexpected_error);
|
|
||||||
|
|
||||||
ioc.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void successful_async_wait() {
|
|
||||||
asio::io_context ioc(1);
|
|
||||||
asio::steady_timer t(ioc);
|
|
||||||
|
|
||||||
t.expires_after(std::chrono::seconds(1));
|
|
||||||
|
|
||||||
t.async_wait(cti::use_continuable)
|
|
||||||
.then([] {
|
|
||||||
puts("Continuation succeeded after 1s as expected!");
|
|
||||||
})
|
|
||||||
.fail(&unexpected_error);
|
|
||||||
|
|
||||||
ioc.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancelled_async_wait() {
|
|
||||||
asio::io_context ioc(1);
|
|
||||||
asio::steady_timer t(ioc);
|
|
||||||
|
|
||||||
t.expires_after(std::chrono::seconds(999));
|
|
||||||
|
|
||||||
t.async_wait(cti::use_continuable)
|
|
||||||
.then([] {
|
|
||||||
puts("This should never be called");
|
|
||||||
std::terminate();
|
|
||||||
})
|
|
||||||
.fail(&check_aborted_operation);
|
|
||||||
|
|
||||||
t.cancel_one();
|
|
||||||
ioc.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void unexpected_error(cti::exception_t e) {
|
|
||||||
if (!bool(e)) {
|
|
||||||
puts("Continuation failed with unexpected cancellation!");
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(e);
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
puts("Continuation failed with unexpected exception");
|
|
||||||
puts(ex.what());
|
|
||||||
} catch (...) {
|
|
||||||
// Rethrow the exception to the asynchronous unhandled exception handler
|
|
||||||
std::rethrow_exception(std::current_exception());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
puts("Continuation failed with unexpected error");
|
|
||||||
puts(e.message().data());
|
|
||||||
#endif
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_aborted_operation(cti::exception_t ex) {
|
|
||||||
if (bool(ex)) {
|
|
||||||
unexpected_error(ex);
|
|
||||||
} else {
|
|
||||||
puts("Continuation failed due to aborted async operation, as expected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
auto through_post(T& postable) {
|
|
||||||
return [&postable](auto&& work) mutable {
|
|
||||||
asio::post(postable, std::forward<decltype(work)>(work));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void using_strand() {
|
|
||||||
asio::io_context ioc(1);
|
|
||||||
asio::io_context::strand strand(ioc);
|
|
||||||
|
|
||||||
asio::post(strand, cti::use_continuable).then([]() {
|
|
||||||
puts("Dispatched through initiation token");
|
|
||||||
});
|
|
||||||
|
|
||||||
cti::async_on(
|
|
||||||
[]() mutable {
|
|
||||||
puts("Dispatched through executor");
|
|
||||||
},
|
|
||||||
through_post(strand));
|
|
||||||
|
|
||||||
ioc.run();
|
|
||||||
}
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.0.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -34,30 +34,12 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
#include <exception>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <asio.hpp>
|
#include <asio.hpp>
|
||||||
|
|
||||||
#include <continuable/continuable.hpp>
|
#include <continuable/continuable.hpp>
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
inline auto error_code_remapper() {
|
|
||||||
return [](auto&& promise, asio::error_code e, auto&&... args) {
|
|
||||||
if (e) {
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
promise.set_exception(std::make_exception_ptr(e));
|
|
||||||
#else
|
|
||||||
promise.set_exception(cti::exception_t(e.value(), e.category()));
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
promise.set_value(std::forward<decltype(args)>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct functional_io_service {
|
struct functional_io_service {
|
||||||
asio::io_context service_;
|
asio::io_context service_;
|
||||||
asio::ip::udp::resolver resolver_;
|
asio::ip::udp::resolver resolver_;
|
||||||
@ -67,11 +49,7 @@ struct functional_io_service {
|
|||||||
|
|
||||||
auto trough_post() noexcept {
|
auto trough_post() noexcept {
|
||||||
return [&](auto&& work) mutable {
|
return [&](auto&& work) mutable {
|
||||||
asio::post(service_,
|
asio::post(service_, std::forward<decltype(work)>(work));
|
||||||
[work = std::forward<decltype(work)>(work)]() mutable {
|
|
||||||
std::move(work)();
|
|
||||||
// .. or: work.set_value();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +61,7 @@ struct functional_io_service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto async_resolve(std::string host, std::string service) {
|
auto async_resolve(std::string host, std::string service) {
|
||||||
return cti::promisify<asio::ip::udp::resolver::iterator>::with(
|
return cti::promisify<asio::ip::udp::resolver::iterator>::from(
|
||||||
error_code_remapper(),
|
|
||||||
[&](auto&&... args) {
|
[&](auto&&... args) {
|
||||||
resolver_.async_resolve(std::forward<decltype(args)>(args)...);
|
resolver_.async_resolve(std::forward<decltype(args)>(args)...);
|
||||||
},
|
},
|
||||||
@ -112,7 +89,7 @@ int main(int, char**) {
|
|||||||
// auto socket = std::make_shared<udp::socket>(service);
|
// auto socket = std::make_shared<udp::socket>(service);
|
||||||
// socket->async_send_to()
|
// socket->async_send_to()
|
||||||
})
|
})
|
||||||
.fail([](cti::exception_t /*error*/) {
|
.fail([](cti::error_type /*error*/) {
|
||||||
// ...
|
// ...
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -32,30 +32,64 @@
|
|||||||
#define CONTINUABLE_BASE_HPP_INCLUDED
|
#define CONTINUABLE_BASE_HPP_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstdint>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/detail/connection/connection-all.hpp>
|
|
||||||
#include <continuable/detail/connection/connection-any.hpp>
|
|
||||||
#include <continuable/detail/connection/connection-seq.hpp>
|
|
||||||
#include <continuable/detail/connection/connection.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_COROUTINE)
|
#include <continuable/detail/base.hpp>
|
||||||
# include <continuable/detail/other/coroutines.hpp>
|
#include <continuable/detail/connection-all.hpp>
|
||||||
#endif // defined(CONTINUABLE_HAS_COROUTINE)
|
#include <continuable/detail/connection-any.hpp>
|
||||||
|
#include <continuable/detail/connection-seq.hpp>
|
||||||
|
#include <continuable/detail/connection.hpp>
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
|
#include <continuable/detail/awaiting.hpp>
|
||||||
|
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Base Base
|
/// \defgroup Base Base
|
||||||
/// provides classes and functions to create continuable_base objects.
|
/// provides classes and functions to create continuable_base objects.
|
||||||
/// \{
|
/// \{
|
||||||
|
|
||||||
|
/// Represents a tag which can be placed first in a signature
|
||||||
|
/// in order to overload callables with the asynchronous result
|
||||||
|
/// as well as an error.
|
||||||
|
///
|
||||||
|
/// See the example below:
|
||||||
|
/// ```cpp
|
||||||
|
/// struct my_callable {
|
||||||
|
/// void operator() (std::string result) {
|
||||||
|
/// // ...
|
||||||
|
/// }
|
||||||
|
/// void operator() (cti::dispatch_error_tag, cti::error_type) {
|
||||||
|
/// // ...
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Will receive errors and results
|
||||||
|
/// continuable.next(my_callable{});
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// \note see continuable::next for details.
|
||||||
|
///
|
||||||
|
/// \since 2.0.0
|
||||||
|
using dispatch_error_tag = detail::types::dispatch_error_tag;
|
||||||
|
|
||||||
|
/// Represents the type that is used as error type
|
||||||
|
///
|
||||||
|
/// By default this type deduces to `std::exception_ptr`.
|
||||||
|
/// If `CONTINUABLE_WITH_NO_EXCEPTIONS` is defined the type
|
||||||
|
/// will be a `std::error_condition`.
|
||||||
|
/// A custom error type may be set through
|
||||||
|
/// defining `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE`.
|
||||||
|
///
|
||||||
|
/// \since 2.0.0
|
||||||
|
using error_type = detail::types::error_type;
|
||||||
|
|
||||||
/// Deduces to a true_type if the given type is a continuable_base.
|
/// Deduces to a true_type if the given type is a continuable_base.
|
||||||
///
|
///
|
||||||
/// \since 3.0.0
|
/// \since 3.0.0
|
||||||
@ -92,10 +126,6 @@ template <typename Data, typename Annotation>
|
|||||||
class continuable_base {
|
class continuable_base {
|
||||||
|
|
||||||
/// \cond false
|
/// \cond false
|
||||||
using ownership = detail::util::ownership;
|
|
||||||
|
|
||||||
using annotation_trait = detail::annotation_trait<Annotation>;
|
|
||||||
|
|
||||||
template <typename, typename>
|
template <typename, typename>
|
||||||
friend class continuable_base;
|
friend class continuable_base;
|
||||||
friend struct detail::base::attorney;
|
friend struct detail::base::attorney;
|
||||||
@ -103,41 +133,25 @@ class continuable_base {
|
|||||||
// The continuation type or intermediate result
|
// The continuation type or intermediate result
|
||||||
Data data_;
|
Data data_;
|
||||||
// The transferable state which represents the validity of the object
|
// The transferable state which represents the validity of the object
|
||||||
ownership ownership_;
|
detail::util::ownership ownership_;
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
/// Constructor accepting the data object while erasing the annotation
|
/// Constructor accepting the data object while erasing the annotation
|
||||||
explicit continuable_base(Data data, ownership ownership)
|
explicit continuable_base(Data data, detail::util::ownership ownership)
|
||||||
: data_(std::move(data))
|
: data_(std::move(data)), ownership_(std::move(ownership)) {
|
||||||
, ownership_(std::move(ownership)) {}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor accepting the data object while erasing the annotation
|
/// Constructor accepting the data object while erasing the annotation
|
||||||
explicit continuable_base(Data data)
|
explicit continuable_base(Data data) : data_(std::move(data)) {
|
||||||
: data_(std::move(data)) {}
|
}
|
||||||
|
|
||||||
/// Constructor accepting any object convertible to the data object,
|
/// Constructor accepting any object convertible to the data object,
|
||||||
/// while erasing the annotation
|
/// while erasing the annotation
|
||||||
template <typename OtherData,
|
template <typename OData, std::enable_if_t<std::is_convertible<
|
||||||
std::enable_if_t<detail::base::can_accept_continuation<
|
std::decay_t<OData>, Data>::value>* = nullptr>
|
||||||
Data, Annotation,
|
continuable_base(OData&& data) : data_(std::forward<OData>(data)) {
|
||||||
detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
|
}
|
||||||
/* implicit */ continuable_base(OtherData&& data)
|
|
||||||
: data_(
|
|
||||||
detail::base::proxy_continuable<Annotation,
|
|
||||||
detail::traits::unrefcv_t<OtherData>>(
|
|
||||||
std::forward<OtherData>(data))) {}
|
|
||||||
|
|
||||||
/// Constructor taking the data of other continuable_base objects
|
|
||||||
/// while erasing the hint.
|
|
||||||
///
|
|
||||||
/// This constructor makes it possible to replace the internal data object of
|
|
||||||
/// the continuable by any object which is useful for type-erasure.
|
|
||||||
template <typename OData,
|
|
||||||
std::enable_if_t<std::is_convertible<
|
|
||||||
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
|
||||||
/* implicit */ continuable_base(continuable_base<OData, Annotation>&& other)
|
|
||||||
: data_(std::move(other).consume()) {}
|
|
||||||
|
|
||||||
/// Constructor taking the data of other continuable_base objects
|
/// Constructor taking the data of other continuable_base objects
|
||||||
/// while erasing the hint.
|
/// while erasing the hint.
|
||||||
@ -145,8 +159,9 @@ public:
|
|||||||
/// This constructor makes it possible to replace the internal data object of
|
/// This constructor makes it possible to replace the internal data object of
|
||||||
/// the continuable by any object which is useful for type-erasure.
|
/// the continuable by any object which is useful for type-erasure.
|
||||||
template <typename OData, typename OAnnotation>
|
template <typename OData, typename OAnnotation>
|
||||||
/* implicit */ continuable_base(continuable_base<OData, OAnnotation>&& other)
|
continuable_base(continuable_base<OData, OAnnotation>&& other)
|
||||||
: continuable_base(std::move(other).finish().consume()) {}
|
: continuable_base(std::move(other).materialize().consume_data()) {
|
||||||
|
}
|
||||||
|
|
||||||
/// \cond false
|
/// \cond false
|
||||||
continuable_base(continuable_base&&) = default;
|
continuable_base(continuable_base&&) = default;
|
||||||
@ -225,17 +240,12 @@ public:
|
|||||||
/// | `Arg` | `continuable_base with <Arg>` |
|
/// | `Arg` | `continuable_base with <Arg>` |
|
||||||
/// | `std::pair<First, Second>` | `continuable_base with <First, Second>` |
|
/// | `std::pair<First, Second>` | `continuable_base with <First, Second>` |
|
||||||
/// | `std::tuple<Args...>` | `continuable_base with <Args...>` |
|
/// | `std::tuple<Args...>` | `continuable_base with <Args...>` |
|
||||||
/// | `cti::result<Args...>` | `continuable_base with <Args...>` |
|
|
||||||
/// | `continuable_base<Arg...>` | `continuable_base with <Args...>` |
|
/// | `continuable_base<Arg...>` | `continuable_base with <Args...>` |
|
||||||
/// Which means the result type of the continuable_base is equal to
|
/// Which means the result type of the continuable_base is equal to
|
||||||
/// the plain types the callback returns (`std::tuple` and
|
/// the plain types the callback returns (`std::tuple` and
|
||||||
/// `std::pair` arguments are unwrapped).
|
/// `std::pair` arguments are unwrapped).
|
||||||
/// A single continuable_base as argument is resolved and the result
|
/// A single continuable_base as argument is resolved and the result
|
||||||
/// type is equal to the resolved continuable_base.
|
/// type is equal to the resolved continuable_base.
|
||||||
/// A cti::result can be used to cancel the continuation or to
|
|
||||||
/// transition to the exception handler.
|
|
||||||
/// The special unwrapping of types can be disabled through wrapping
|
|
||||||
/// such objects through a call to cti::make_plain.
|
|
||||||
/// Consider the following examples:
|
/// Consider the following examples:
|
||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// http_request("github.com")
|
/// http_request("github.com")
|
||||||
@ -257,17 +267,6 @@ public:
|
|||||||
/// http_request("github.com")
|
/// http_request("github.com")
|
||||||
/// .then([](std::string github) { return http_request("atom.io"); })
|
/// .then([](std::string github) { return http_request("atom.io"); })
|
||||||
/// .then([](std::string atom) { }); // <std::string>
|
/// .then([](std::string atom) { }); // <std::string>
|
||||||
///
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) -> result<std::string> {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// })
|
|
||||||
/// .fail([] -> result<std::string> {
|
|
||||||
/// return recover("Hello World!");
|
|
||||||
/// })
|
|
||||||
/// .then([](std::string content) -> result<std::string> {
|
|
||||||
/// return cancel();
|
|
||||||
/// })
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// \since 1.0.0
|
/// \since 1.0.0
|
||||||
@ -276,7 +275,7 @@ public:
|
|||||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||||
return detail::base::chain_continuation<detail::base::handle_results::yes,
|
return detail::base::chain_continuation<detail::base::handle_results::yes,
|
||||||
detail::base::handle_errors::no>(
|
detail::base::handle_errors::no>(
|
||||||
std::move(*this).finish(), std::forward<T>(callback),
|
std::move(*this).materialize(), std::forward<T>(callback),
|
||||||
std::forward<E>(executor));
|
std::forward<E>(executor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +301,7 @@ public:
|
|||||||
template <typename OData, typename OAnnotation>
|
template <typename OData, typename OAnnotation>
|
||||||
auto then(continuable_base<OData, OAnnotation>&& continuation) && {
|
auto then(continuable_base<OData, OAnnotation>&& continuation) && {
|
||||||
return std::move(*this).then(
|
return std::move(*this).then(
|
||||||
detail::base::wrap_continuation(std::move(continuation).finish()));
|
detail::base::wrap_continuation(std::move(continuation).materialize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Main method of the continuable_base to catch exceptions and error codes
|
/// Main method of the continuable_base to catch exceptions and error codes
|
||||||
@ -317,18 +316,12 @@ public:
|
|||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// http_request("github.com")
|
/// http_request("github.com")
|
||||||
/// .then([](std::string github) { })
|
/// .then([](std::string github) { })
|
||||||
/// .fail([](std::exception_ptr ep) {
|
/// .fail([](std::exception_ptr ptr) {
|
||||||
/// // Check whether the exception_ptr is valid (not default constructed)
|
/// // Handle the error here
|
||||||
/// // if bool(ep) == false this means that the operation was cancelled
|
/// try {
|
||||||
/// // by the user or application (promise.set_canceled() or
|
/// std::rethrow_exception(ptr);
|
||||||
/// // make_cancelling_continuable()).
|
/// } catch (std::exception& e) {
|
||||||
/// if (ep) {
|
/// e.what(); // Handle the exception
|
||||||
/// // Handle the error here
|
|
||||||
/// try {
|
|
||||||
/// std::rethrow_exception(ep);
|
|
||||||
/// } catch (std::exception& e) {
|
|
||||||
/// e.what(); // Handle the exception
|
|
||||||
/// }
|
|
||||||
/// }
|
/// }
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
@ -348,26 +341,14 @@ public:
|
|||||||
/// \returns Returns a continuable_base with an asynchronous return type
|
/// \returns Returns a continuable_base with an asynchronous return type
|
||||||
/// depending on the previous result type.
|
/// depending on the previous result type.
|
||||||
///
|
///
|
||||||
/// \attention The given exception type exception_t can be passed to the
|
|
||||||
/// handler in a default constructed state <br>`bool(e) == false`.
|
|
||||||
/// This always means that the operation was cancelled by the user,
|
|
||||||
/// possibly through:
|
|
||||||
/// - \ref promise_base::set_canceled
|
|
||||||
/// - \ref make_cancelling_continuable
|
|
||||||
/// - \ref result::set_canceled
|
|
||||||
/// - \ref cancel<br>
|
|
||||||
/// In that case the exception can be ignored safely (but it is
|
|
||||||
/// recommended not to proceed, although it is possible to
|
|
||||||
/// recover from the cancellation).
|
|
||||||
///
|
///
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
template <typename T, typename E = detail::types::this_thread_executor_tag>
|
template <typename T, typename E = detail::types::this_thread_executor_tag>
|
||||||
auto fail(T&& callback,
|
auto fail(T&& callback,
|
||||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||||
return detail::base::chain_continuation<
|
return detail::base::chain_continuation<detail::base::handle_results::no,
|
||||||
detail::base::handle_results::no, detail::base::handle_errors::forward>(
|
detail::base::handle_errors::plain>(
|
||||||
std::move(*this).finish(),
|
std::move(*this).materialize(), std::forward<T>(callback),
|
||||||
detail::base::strip_exception_arg(std::forward<T>(callback)),
|
|
||||||
std::forward<E>(executor));
|
std::forward<E>(executor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,11 +370,9 @@ public:
|
|||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
template <typename OData, typename OAnnotation>
|
template <typename OData, typename OAnnotation>
|
||||||
auto fail(continuable_base<OData, OAnnotation>&& continuation) && {
|
auto fail(continuable_base<OData, OAnnotation>&& continuation) && {
|
||||||
return std::move(*this) //
|
continuation.freeze();
|
||||||
.fail([continuation = std::move(continuation).freeze()] //
|
return std::move(*this).fail([continuation = std::move(continuation)](
|
||||||
(exception_t) mutable {
|
error_type) mutable { std::move(continuation).done(); });
|
||||||
std::move(continuation).done(); //
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A method which allows to use an overloaded callable for the error
|
/// A method which allows to use an overloaded callable for the error
|
||||||
@ -407,7 +386,7 @@ public:
|
|||||||
/// void operator() (std::string result) {
|
/// void operator() (std::string result) {
|
||||||
/// // ...
|
/// // ...
|
||||||
/// }
|
/// }
|
||||||
/// void operator() (cti::exception_arg_t, cti::exception_t) {
|
/// void operator() (cti::dispatch_error_tag, cti::error_type) {
|
||||||
/// // ...
|
/// // ...
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -428,56 +407,22 @@ public:
|
|||||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||||
return detail::base::chain_continuation<
|
return detail::base::chain_continuation<
|
||||||
detail::base::handle_results::yes,
|
detail::base::handle_results::yes,
|
||||||
detail::base::handle_errors::forward>(std::move(*this).finish(),
|
detail::base::handle_errors::forward>(std::move(*this).materialize(),
|
||||||
std::forward<T>(callback),
|
std::forward<T>(callback),
|
||||||
std::forward<E>(executor));
|
std::forward<E>(executor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a continuable_base which continues its invocation through the
|
/// A method which allows to apply this continuable to the given callable.
|
||||||
/// given executor.
|
|
||||||
///
|
///
|
||||||
/// \returns Returns a continuable_base of the same type.
|
/// \param transform A transform which shall accept this continuable
|
||||||
///
|
|
||||||
/// \since 4.2.0
|
|
||||||
template <typename E>
|
|
||||||
auto via(E&& executor) && {
|
|
||||||
return std::move(*this).next(
|
|
||||||
[](auto&&... args) {
|
|
||||||
return make_result(std::forward<decltype(args)>(args)...);
|
|
||||||
},
|
|
||||||
std::forward<E>(executor));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a continuable_base which will have its signature converted
|
|
||||||
/// to the given Args.
|
|
||||||
///
|
|
||||||
/// A signature can only be converted if it can be partially applied
|
|
||||||
/// from the previous one as shown below:
|
|
||||||
/// ```cpp
|
|
||||||
/// continuable<long> c = make_ready_continuable(0, 1, 2).as<long>();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \returns Returns a continuable_base with an asynchronous return type
|
|
||||||
/// matching the given Args.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename... Args>
|
|
||||||
auto as() && {
|
|
||||||
return std::move(*this).then(detail::base::convert_to<Args...>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A method which allows to apply a callable object to this continuable.
|
|
||||||
///
|
|
||||||
/// \param transform A callable objects that transforms a continuable
|
|
||||||
/// to a different object.
|
|
||||||
///
|
///
|
||||||
/// \returns Returns the result of the given transform when this
|
/// \returns Returns the result of the given transform when this
|
||||||
/// continuable is passed into it.
|
/// continuable is passed into it.
|
||||||
///
|
///
|
||||||
/// \since 4.0.0
|
/// \since 2.0.0
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto apply(T&& transform) && {
|
auto apply(T&& transform) && {
|
||||||
return std::forward<T>(transform)(std::move(*this).finish());
|
return std::forward<T>(transform)(std::move(*this).materialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The pipe operator | is an alias for the continuable::then method.
|
/// The pipe operator | is an alias for the continuable::then method.
|
||||||
@ -493,6 +438,22 @@ public:
|
|||||||
return std::move(*this).then(std::forward<T>(right));
|
return std::move(*this).then(std::forward<T>(right));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The pipe operator | is an alias for the continuable::apply method.
|
||||||
|
///
|
||||||
|
/// \param transform The transformer which is applied.
|
||||||
|
///
|
||||||
|
/// \returns See the corresponding continuable_base::apply method for the
|
||||||
|
/// explanation of the return type.
|
||||||
|
///
|
||||||
|
/// \note You may create your own transformation through
|
||||||
|
/// calling make_transformation.
|
||||||
|
///
|
||||||
|
/// \since 3.0.0
|
||||||
|
template <typename T>
|
||||||
|
auto operator|(detail::types::transform<T> transform) && {
|
||||||
|
return std::move(*this).apply(std::move(transform));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes both continuable_base objects parallel and calls the
|
/// Invokes both continuable_base objects parallel and calls the
|
||||||
/// callback with the result of both continuable_base objects.
|
/// callback with the result of both continuable_base objects.
|
||||||
///
|
///
|
||||||
@ -611,64 +572,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \since 1.0.0
|
/// \since 1.0.0
|
||||||
void done() && {
|
void done() && {
|
||||||
detail::base::finalize_continuation(std::move(*this).finish());
|
detail::base::finalize_continuation(std::move(*this));
|
||||||
}
|
|
||||||
|
|
||||||
/// Materializes the continuation expression template and finishes
|
|
||||||
/// the current applied strategy such that the resulting continuable
|
|
||||||
/// will always be a concrete type and Continuable::is_concrete holds.
|
|
||||||
///
|
|
||||||
/// This can be used in the case where we are chaining continuations lazily
|
|
||||||
/// through a strategy, for instance when applying operators for
|
|
||||||
/// expressing connections and then want to return a materialized
|
|
||||||
/// continuable_base which uses the strategy respectively.
|
|
||||||
/// ```cpp
|
|
||||||
/// auto do_both() {
|
|
||||||
/// return (wait(10s) || wait_key_pressed(KEY_SPACE)).finish();
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // Without a call to finish() this would lead to
|
|
||||||
/// // an unintended evaluation strategy:
|
|
||||||
/// do_both() || wait(5s);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \note When using a type erased continuable_base such as
|
|
||||||
/// `continuable<...>` this method doesn't need to be called
|
|
||||||
/// since the continuable_base is materialized automatically
|
|
||||||
/// on conversion.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
auto finish() && {
|
|
||||||
return annotation_trait::finish(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true when the continuable can provide its result immediately,
|
|
||||||
/// and its lazy invocation would be side-effect free.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
bool is_ready() const noexcept {
|
|
||||||
return annotation_trait::is_ready(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invalidates the continuable and returns its immediate invocation result.
|
|
||||||
///
|
|
||||||
/// This method can be used to specialize the asynchronous control flow
|
|
||||||
/// based on whether the continuable_base is_ready at every time,
|
|
||||||
/// which is true for a continuable created through the following functions:
|
|
||||||
/// - make_ready_continuable
|
|
||||||
/// - make_exceptional_continuable
|
|
||||||
///
|
|
||||||
/// \returns A result<Args...> where Args... represent the current
|
|
||||||
/// asynchronous parameters or the currently stored exception.
|
|
||||||
///
|
|
||||||
/// \attention unpack requires that continuable_base::is_ready returned true
|
|
||||||
/// in a previous check, otherwise its behaviour is unspecified.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
auto unpack() && {
|
|
||||||
assert(ownership_.is_acquired());
|
|
||||||
assert(is_ready());
|
|
||||||
return detail::base::attorney::query(std::move(*this).finish());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Predicate to check whether the cti::continuable_base is frozen or not.
|
/// Predicate to check whether the cti::continuable_base is frozen or not.
|
||||||
@ -714,7 +618,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \cond false
|
/// \cond false
|
||||||
#if defined(CONTINUABLE_HAS_COROUTINE)
|
#ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
/// \endcond
|
/// \endcond
|
||||||
/// Implements the operator for awaiting on continuables using `co_await`.
|
/// Implements the operator for awaiting on continuables using `co_await`.
|
||||||
///
|
///
|
||||||
@ -740,47 +644,49 @@ public:
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// In case the library is configured to use error codes or a custom
|
/// In case the library is configured to use error codes or a custom
|
||||||
/// exception type the return type of the co_await expression is changed.
|
/// error type the return type of the co_await expression is changed.
|
||||||
/// The result is returned through a cti::result<...>.
|
/// The result is returned through an internal proxy object which may
|
||||||
|
/// be queried for the error object.
|
||||||
/// | Continuation type | co_await returns |
|
/// | Continuation type | co_await returns |
|
||||||
/// | : ------------------------------- | : -------------------------------- |
|
/// | : ------------------------------- | : -------------------------------- |
|
||||||
/// | `continuable_base with <>` | `result<void>` |
|
/// | `continuable_base with <>` | `unspecified<void>` |
|
||||||
/// | `continuable_base with <Arg>` | `result<Arg>` |
|
/// | `continuable_base with <Arg>` | `unspecified<Arg>` |
|
||||||
/// | `continuable_base with <Args...>` | `result<Args...>` |
|
/// | `continuable_base with <Args...>` | `unspecified<std::tuple<Args...>>` |
|
||||||
///
|
/// The interface of the proxy object is similar to the one proposed in
|
||||||
/// \note Using continuable_base as return type for coroutines
|
/// the `std::expected` proposal:
|
||||||
/// is supported. The coroutine is initially stopped and
|
|
||||||
/// resumed when the continuation is requested in order to
|
|
||||||
/// keep the lazy evaluation semantics of the continuable_base.
|
|
||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// cti::continuable<> resolve_async_void() {
|
/// if (auto&& result = co_await http_request("github.com")) {
|
||||||
/// co_await http_request("github.com");
|
/// auto value = *result;
|
||||||
/// // ...
|
/// } else {
|
||||||
/// co_return;
|
/// cti::error_type error = result.get_exception();
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// cti::continuable<int> resolve_async() {
|
/// auto result = co_await http_request("github.com");
|
||||||
|
/// bool(result);
|
||||||
|
/// result.is_value();
|
||||||
|
/// result.is_exception();
|
||||||
|
/// *result; // Same as result.get_value()
|
||||||
|
/// result.get_value();
|
||||||
|
/// result.get_exception();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// \attention Note that it isn't possible as of now to use a continuable
|
||||||
|
/// as return type from coroutines as depicted below:
|
||||||
|
/// ```cpp
|
||||||
|
/// cti::continuable<int> do_sth() {
|
||||||
/// co_await http_request("github.com");
|
/// co_await http_request("github.com");
|
||||||
/// // ...
|
/// // ...
|
||||||
/// co_return 0;
|
/// co_return 0;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// It's possible to return multiple return values from coroutines
|
/// Propably this will be added in a future version of the library.
|
||||||
/// by wrapping those in a tuple like type:
|
|
||||||
/// ```cpp
|
|
||||||
/// cti::continuable<int, int, int> resolve_async_multiple() {
|
|
||||||
/// co_await http_request("github.com");
|
|
||||||
/// // ...
|
|
||||||
/// co_return std::make_tuple(0, 1, 2);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
///
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
auto operator co_await() && {
|
auto operator co_await() && {
|
||||||
return detail::awaiting::create_awaiter(std::move(*this).finish());
|
return detail::awaiting::create_awaiter(std::move(*this).materialize());
|
||||||
}
|
}
|
||||||
/// \cond false
|
/// \cond false
|
||||||
#endif // defined(CONTINUABLE_HAS_COROUTINE)
|
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -788,7 +694,12 @@ private:
|
|||||||
ownership_.release();
|
ownership_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Data&& consume() && {
|
auto materialize() && {
|
||||||
|
return detail::connection::materializer<continuable_base>::apply(
|
||||||
|
std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
Data&& consume_data() && {
|
||||||
assert_acquired();
|
assert_acquired();
|
||||||
release();
|
release();
|
||||||
return std::move(data_);
|
return std::move(data_);
|
||||||
@ -892,9 +803,9 @@ constexpr auto make_continuable(Continuation&& continuation) {
|
|||||||
"use make_continuable<void>(...). Continuables with an exact "
|
"use make_continuable<void>(...). Continuables with an exact "
|
||||||
"signature may be created through make_continuable<Args...>.");
|
"signature may be created through make_continuable<Args...>.");
|
||||||
|
|
||||||
return detail::base::attorney::create_from(
|
return detail::base::attorney::create(
|
||||||
std::forward<Continuation>(continuation),
|
std::forward<Continuation>(continuation),
|
||||||
typename detail::hints::from_args<Args...>::type{},
|
detail::hints::extract(detail::traits::identity<Args...>{}),
|
||||||
detail::util::ownership{});
|
detail::util::ownership{});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,18 +815,46 @@ constexpr auto make_continuable(Continuation&& continuation) {
|
|||||||
/// \attention Usually using this function isn't needed at all since
|
/// \attention Usually using this function isn't needed at all since
|
||||||
/// the continuable library is capable of working with
|
/// the continuable library is capable of working with
|
||||||
/// plain values in most cases.
|
/// plain values in most cases.
|
||||||
/// Try not to use it since it causes unnecessary recursive
|
/// Try not to use it since it causes unneccessary recursive
|
||||||
/// function calls.
|
/// function calls.
|
||||||
///
|
///
|
||||||
/// \since 3.0.0
|
/// \since 3.0.0
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto make_ready_continuable(Args&&... args) {
|
constexpr auto make_ready_continuable() {
|
||||||
return detail::base::attorney::create_from_raw(
|
return make_continuable<void>([](auto&& promise) {
|
||||||
detail::base::ready_continuation<detail::traits::unrefcv_t<Args>...>(
|
std::forward<decltype(promise)>(promise).set_value();
|
||||||
result<detail::traits::unrefcv_t<Args>...>::from(
|
});
|
||||||
std::forward<Args>(args)...)),
|
}
|
||||||
detail::identity<detail::traits::unrefcv_t<Args>...>{},
|
|
||||||
detail::util::ownership{});
|
/// Returns a continuable_base with one result value which instantly resolves
|
||||||
|
/// the promise with the given value.
|
||||||
|
///
|
||||||
|
/// \copydetails make_ready_continuable()
|
||||||
|
template <typename Result>
|
||||||
|
constexpr auto make_ready_continuable(Result&& result) {
|
||||||
|
return make_continuable<std::decay_t<Result>>( // ...
|
||||||
|
[result = std::forward<Result>(result)](auto&& promise) mutable {
|
||||||
|
std::forward<decltype(promise)>(promise).set_value(std::move(result));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a continuable_base with multiple result values which instantly
|
||||||
|
/// resolves the promise with the given values.
|
||||||
|
///
|
||||||
|
/// \copydetails make_ready_continuable()
|
||||||
|
template <typename FirstResult, typename SecondResult, typename... Rest>
|
||||||
|
constexpr auto make_ready_continuable(FirstResult&& first_result,
|
||||||
|
SecondResult&& second_result,
|
||||||
|
Rest&&... rest) {
|
||||||
|
return make_continuable<std::decay_t<FirstResult>, std::decay_t<SecondResult>,
|
||||||
|
std::decay_t<Rest>...>( // ...
|
||||||
|
[result = std::make_tuple(std::forward<FirstResult>(first_result),
|
||||||
|
std::forward<SecondResult>(second_result),
|
||||||
|
std::forward<Rest>(rest)...)](
|
||||||
|
auto&& promise) mutable {
|
||||||
|
detail::traits::unpack(result,
|
||||||
|
std::forward<decltype(promise)>(promise));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a continuable_base with the parameterized result which instantly
|
/// Returns a continuable_base with the parameterized result which instantly
|
||||||
@ -928,213 +867,20 @@ auto make_ready_continuable(Args&&... args) {
|
|||||||
/// auto ct = cti::make_exceptional_continuable<int>(ptr);
|
/// auto ct = cti::make_exceptional_continuable<int>(ptr);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// \tparam Args The fake signature of the returned continuable.
|
|
||||||
///
|
|
||||||
/// \since 3.0.0
|
|
||||||
template <typename... Args, typename Exception>
|
|
||||||
constexpr auto make_exceptional_continuable(Exception&& exception) {
|
|
||||||
static_assert(sizeof...(Args) > 0,
|
|
||||||
"Requires at least one type for the fake signature!");
|
|
||||||
|
|
||||||
using hint_t = typename detail::hints::from_args<Args...>::type;
|
|
||||||
using ready_continuation_t = typename detail::base::
|
|
||||||
ready_continuation_from_hint<hint_t>::type;
|
|
||||||
using result_t = typename detail::base::result_from_hint<hint_t>::type;
|
|
||||||
return detail::base::attorney::create_from_raw(
|
|
||||||
ready_continuation_t(result_t::from(exception_arg_t{},
|
|
||||||
std::forward<Exception>(exception))),
|
|
||||||
hint_t{}, detail::util::ownership{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a continuable_base with the parameterized result which never
|
|
||||||
/// resolves its promise and thus cancels the asynchronous continuation chain
|
|
||||||
/// through throwing a default constructed exception_t.
|
|
||||||
///
|
|
||||||
/// This can be used to cancel an asynchronous continuation chain when
|
|
||||||
/// returning a continuable_base from a handler where other paths could
|
|
||||||
/// possibly continue the asynchronous chain. See an example below:
|
|
||||||
/// ```cpp
|
|
||||||
/// do_sth().then([weak = this->weak_from_this()]() -> continuable<> {
|
|
||||||
/// if (auto me = weak.lock()) {
|
|
||||||
/// return do_sth_more();
|
|
||||||
/// } else {
|
|
||||||
/// // Abort the asynchronous continuation chain since the
|
|
||||||
/// // weakly referenced object expired previously.
|
|
||||||
/// return make_cancelling_continuable<void>();
|
|
||||||
/// }
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
/// The default unhandled exception handler ignores exception types
|
|
||||||
/// that don't evaluate to true when being converted to a bool.
|
|
||||||
/// This saves expensive construction of std::exception_ptr or similar types,
|
|
||||||
/// where only one exception type is used for signaling the cancellation.
|
|
||||||
///
|
|
||||||
/// \tparam Signature The fake signature of the returned continuable.
|
/// \tparam Signature The fake signature of the returned continuable.
|
||||||
///
|
///
|
||||||
/// \since 4.0.0
|
/// \since 3.0.0
|
||||||
template <typename... Signature>
|
template <typename... Signature, typename Exception>
|
||||||
auto make_cancelling_continuable() {
|
constexpr auto make_exceptional_continuable(Exception&& exception) {
|
||||||
static_assert(sizeof...(Signature) > 0,
|
static_assert(sizeof...(Signature) > 0,
|
||||||
"Requires at least one type for the fake signature!");
|
"Requires at least one type for the fake signature!");
|
||||||
|
|
||||||
return make_exceptional_continuable<Signature...>(exception_t{});
|
return make_continuable<Signature...>( // ...
|
||||||
|
[exception = std::forward<Exception>(exception)](auto&& promise) mutable {
|
||||||
|
std::forward<decltype(promise)>(promise).set_exception(
|
||||||
|
std::move(exception));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Can be used to disable the special meaning for a returned value in
|
|
||||||
/// asynchronous handler functions.
|
|
||||||
///
|
|
||||||
/// Several types have a special meaning when being returned from a callable
|
|
||||||
/// passed to asynchronous handler functions like:
|
|
||||||
/// - continuable_base::then
|
|
||||||
/// - continuable_base::fail
|
|
||||||
/// - continuable_base::next
|
|
||||||
///
|
|
||||||
/// For instance such types are std::tuple, std::pair and cti::result.
|
|
||||||
///
|
|
||||||
/// Wrapping such an object through a call to make_plain disables the special
|
|
||||||
/// meaning for such objects as shown below:
|
|
||||||
/// ```cpp
|
|
||||||
/// continuable<result<int, int> c = http_request("example.com")
|
|
||||||
/// .then([](std::string content) {
|
|
||||||
/// return make_plain(make_result(0, 1));
|
|
||||||
/// })
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename T>
|
|
||||||
auto make_plain(T&& value) {
|
|
||||||
return plain_t<detail::traits::unrefcv_t<T>>(std::forward<T>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to recover to from a failure handler,
|
|
||||||
/// the result handler which comes after will be called with the
|
|
||||||
/// corresponding result.
|
|
||||||
///
|
|
||||||
/// The \ref exceptional_result returned by this function can be returned
|
|
||||||
/// from any result or failure handler in order to rethrow the exception.
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) {
|
|
||||||
/// return recover(1, 2);
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) {
|
|
||||||
/// return recover(1, 2);
|
|
||||||
/// })
|
|
||||||
/// .then([](int a, int b) {
|
|
||||||
/// // Recovered from the failure
|
|
||||||
/// })
|
|
||||||
/// ```
|
|
||||||
/// A corresponding \ref result is returned by \ref recover
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) -> cti::result<int, int> {
|
|
||||||
/// return recover(1, 2);
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) -> cti::result<int, int> {
|
|
||||||
/// return recover(1, 2);
|
|
||||||
/// })
|
|
||||||
/// .then([](int a, int b) -> cti::result<int, int> {
|
|
||||||
/// // Recovered from the failure
|
|
||||||
/// })
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename... Args>
|
|
||||||
result<detail::traits::unrefcv_t<Args>...> recover(Args&&... args) {
|
|
||||||
return make_result(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to rethrow an exception to the asynchronous continuation chain,
|
|
||||||
/// the failure handler which comes after will be called with the
|
|
||||||
/// corresponding exception.
|
|
||||||
///
|
|
||||||
/// The \ref exceptional_result returned by this function can be returned
|
|
||||||
/// from any result or failure handler in order to rethrow the exception.
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// })
|
|
||||||
/// .next([](auto&&...) {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
/// The returned \ref exceptional_result is convertible to
|
|
||||||
/// any \ref result as shown below:
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) -> cti::result<> {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) -> cti::result<> {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// })
|
|
||||||
/// .next([](auto&&...) -> cti::result<> {
|
|
||||||
/// return rethrow(std::make_exception_ptr(std::exception{}));
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
|
||||||
inline exceptional_result rethrow(exception_t exception) {
|
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
|
|
||||||
return exceptional_result{std::move(exception)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to cancel an asynchronous continuation chain,
|
|
||||||
/// the next failure handler which comes after cancel will be called
|
|
||||||
/// with a default constructed exception_t object.
|
|
||||||
///
|
|
||||||
/// The \ref cancellation_result returned by this function can be returned from
|
|
||||||
/// any result or failure handler in order to cancel the chain.
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) {
|
|
||||||
/// return cancel();
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) {
|
|
||||||
/// return cancel();
|
|
||||||
/// })
|
|
||||||
/// .next([](auto&&...) {
|
|
||||||
/// return cancel();
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
/// The returned \ref empty_result is convertible to
|
|
||||||
/// any \ref result as shown below:
|
|
||||||
/// ```cpp
|
|
||||||
/// http_request("example.com")
|
|
||||||
/// .then([](std::string content) -> cti::result<> {
|
|
||||||
/// return cancel();
|
|
||||||
/// })
|
|
||||||
/// .fail([](cti::exception_t exception) -> cti::result<> {
|
|
||||||
/// return cancel();
|
|
||||||
/// })
|
|
||||||
/// .next([](auto&&...) -> cti::result<> {
|
|
||||||
/// return cancel();
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
inline cancellation_result cancel() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to stop an asynchronous continuation chain,
|
|
||||||
/// no handler which comes after stop was received won't be called.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
inline empty_result stop() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \}
|
/// \}
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -35,11 +35,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <continuable/detail/connection/connection-all.hpp>
|
|
||||||
#include <continuable/detail/connection/connection-any.hpp>
|
#include <continuable/detail/connection-all.hpp>
|
||||||
#include <continuable/detail/connection/connection-seq.hpp>
|
#include <continuable/detail/connection-any.hpp>
|
||||||
#include <continuable/detail/connection/connection.hpp>
|
#include <continuable/detail/connection-seq.hpp>
|
||||||
#include <continuable/detail/traversal/range.hpp>
|
#include <continuable/detail/connection.hpp>
|
||||||
|
#include <continuable/detail/range.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Connections Connections
|
/// \defgroup Connections Connections
|
||||||
|
|||||||
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_COROUTINE_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_COROUTINE_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-types.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_COROUTINE)
|
|
||||||
# include <continuable/detail/other/coroutines.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
/// Is thrown from co_await expressions if the awaited continuable is canceled
|
|
||||||
///
|
|
||||||
/// Default constructed exception types that are returned by a cancelled
|
|
||||||
/// continuable are converted automatically to await_canceled_exception when
|
|
||||||
/// being returned by a co_await expression.
|
|
||||||
///
|
|
||||||
/// The await_canceled_exception gets converted again to a default constructed
|
|
||||||
/// exception type if it becomes unhandled inside a coroutine which
|
|
||||||
/// returns a continuable_base.
|
|
||||||
/// ```cpp
|
|
||||||
/// continuable<> cancelled_coroutine() {
|
|
||||||
/// co_await make_cancelling_continuable<void>();
|
|
||||||
///
|
|
||||||
/// co_return;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // ...
|
|
||||||
///
|
|
||||||
/// cancelled_coroutine().fail([](exception_t e) {
|
|
||||||
/// assert(bool(e) == false);
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
using await_canceled_exception = detail::awaiting::await_canceled_exception;
|
|
||||||
# endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
/// \cond false
|
|
||||||
// As far as I know there is no other way to implement this specialization...
|
|
||||||
// NOLINTNEXTLINE(cert-dcl58-cpp)
|
|
||||||
namespace std {
|
|
||||||
# if defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
namespace experimental {
|
|
||||||
# endif // defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
template <typename Data, typename... Args, typename... FunctionArgs>
|
|
||||||
struct coroutine_traits<
|
|
||||||
cti::continuable_base<Data, cti::detail::identity<Args...>>,
|
|
||||||
FunctionArgs...> {
|
|
||||||
|
|
||||||
using promise_type = cti::detail::awaiting::promise_type<
|
|
||||||
cti::continuable<Args...>, cti::promise<Args...>, Args...>;
|
|
||||||
};
|
|
||||||
# if defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
} // namespace experimental
|
|
||||||
# endif // defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
} // namespace std
|
|
||||||
/// \endcond
|
|
||||||
#endif // defined(CONTINUABLE_HAS_COROUTINE)
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_COROUTINE_HPP_INCLUDED
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_OPERATIONS_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_OPERATIONS_HPP_INCLUDED
|
|
||||||
|
|
||||||
/// \defgroup Operations Operations
|
|
||||||
/// provides functions to work with asynchronous control flows.
|
|
||||||
|
|
||||||
#include <continuable/operations/async.hpp>
|
|
||||||
#include <continuable/operations/loop.hpp>
|
|
||||||
#include <continuable/operations/split.hpp>
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_OPERATIONS_HPP_INCLUDED
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/utility/identity.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \defgroup Primitives Primitives
|
|
||||||
/// provides basic tag types for creating a customized callbacks
|
|
||||||
/// and continuations.
|
|
||||||
///
|
|
||||||
/// For the callback and the continuation `Args...` represents the
|
|
||||||
/// asynchronous result:
|
|
||||||
/// ```cpp
|
|
||||||
/// template<typename... Args>
|
|
||||||
/// struct continuation {
|
|
||||||
/// void operator() (callback<Args...>);
|
|
||||||
/// bool operator() (cti::is_ready_arg_t) const;
|
|
||||||
/// result<Args...> operator() (cti::unpack_arg_t);
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
/// ```cpp
|
|
||||||
/// template<typename... Args>
|
|
||||||
/// struct callback {
|
|
||||||
/// void operator() (Args...) &&;
|
|
||||||
/// void operator() (cti::exception_arg_t, cti::exception_t) &&;
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// Represents the tag type that is used to specify the signature hint
|
|
||||||
/// of a continuable_base or promise_base.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename... Args>
|
|
||||||
using signature_arg_t = detail::identity<Args...>;
|
|
||||||
|
|
||||||
/// Represents the tag type that is used to query the continuation
|
|
||||||
/// for whether it resolves the callback instantly with its arguments
|
|
||||||
/// without having side effects.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
struct is_ready_arg_t {};
|
|
||||||
|
|
||||||
/// Represents the tag type that is used to unpack the result of a continuation.
|
|
||||||
///
|
|
||||||
/// \attention It's required that the query of is_ready_arg_t returns true,
|
|
||||||
/// otherwise the behaviour when unpacking is unspecified.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
struct unpack_arg_t {};
|
|
||||||
|
|
||||||
/// \copydoc unpack_arg_t
|
|
||||||
///
|
|
||||||
/// \deprecated The query_arg_t was deprecated because of
|
|
||||||
/// its new naming unpack_arg_t.
|
|
||||||
///
|
|
||||||
[[deprecated("The dispatch_error_tag was replaced by unpack_arg_t and will "
|
|
||||||
"be removed in a later major version!")]] //
|
|
||||||
typedef unpack_arg_t query_arg_t;
|
|
||||||
|
|
||||||
/// Represents the tag type that is used to disambiguate the
|
|
||||||
/// callback operator() in order to take the exception asynchronous chain.
|
|
||||||
///
|
|
||||||
/// \note see continuable::next for details.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
struct exception_arg_t {};
|
|
||||||
|
|
||||||
/// \copydoc exception_arg_t
|
|
||||||
///
|
|
||||||
/// \deprecated The dispatch_error_tag was deprecated in order to move closer
|
|
||||||
/// to the types specified in the "A Unified Future" proposal
|
|
||||||
/// especially regarding naming types similar.
|
|
||||||
///
|
|
||||||
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
|
|
||||||
"be removed in a later major version!")]] //
|
|
||||||
typedef exception_arg_t dispatch_error_tag;
|
|
||||||
|
|
||||||
/// Represents the type that is used as exception type
|
|
||||||
///
|
|
||||||
/// By default this type deduces to `std::exception_ptr`.
|
|
||||||
/// If `CONTINUABLE_WITH_NO_EXCEPTIONS` is defined the type
|
|
||||||
/// will be a `std::error_condition`.
|
|
||||||
/// A custom error type may be set through
|
|
||||||
/// defining `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE`.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
using exception_t = detail::types::exception_t;
|
|
||||||
|
|
||||||
/// \copydoc exception_t
|
|
||||||
///
|
|
||||||
/// \deprecated The error_type was deprecated in order to move closer
|
|
||||||
/// to the types specified in the "A Unified Future" proposal
|
|
||||||
/// especially regarding naming types similar.
|
|
||||||
///
|
|
||||||
[[deprecated("The error_type was replaced by exception_t and will "
|
|
||||||
"be removed in a later major version!")]] //
|
|
||||||
typedef exception_t error_type;
|
|
||||||
|
|
||||||
/// Represents the type that is used to disable the special meaning of types
|
|
||||||
/// which are returned by a asynchronous result handler.
|
|
||||||
/// See cti::plain for details.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename T>
|
|
||||||
using plain_t = detail::types::plain_tag<T>;
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -31,14 +31,12 @@
|
|||||||
#ifndef CONTINUABLE_PROMISE_BASE_HPP_INCLUDED
|
#ifndef CONTINUABLE_PROMISE_BASE_HPP_INCLUDED
|
||||||
#define CONTINUABLE_PROMISE_BASE_HPP_INCLUDED
|
#define CONTINUABLE_PROMISE_BASE_HPP_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
#include <continuable/detail/hints.hpp>
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/util.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Base Base
|
/// \defgroup Base Base
|
||||||
@ -53,7 +51,7 @@ namespace cti {
|
|||||||
///
|
///
|
||||||
/// If we want to resolve the promise_base trough the call operator,
|
/// If we want to resolve the promise_base trough the call operator,
|
||||||
/// and we want to resolve it through an exception, we must call it with a
|
/// and we want to resolve it through an exception, we must call it with a
|
||||||
/// exception_arg_t as first and the exception as second argument.
|
/// dispatch_error_tag as first and the exception as second argument.
|
||||||
/// Additionally the promise is resolveable only through its call
|
/// Additionally the promise is resolveable only through its call
|
||||||
/// operator when invoked as an r-value.
|
/// operator when invoked as an r-value.
|
||||||
///
|
///
|
||||||
@ -64,7 +62,7 @@ class promise_base
|
|||||||
/// \cond false
|
/// \cond false
|
||||||
;
|
;
|
||||||
template <typename Data, typename... Args>
|
template <typename Data, typename... Args>
|
||||||
class promise_base<Data, detail::identity<Args...>>
|
class promise_base<Data, detail::hints::signature_hint_tag<Args...>>
|
||||||
: detail::util::non_copyable
|
: detail::util::non_copyable
|
||||||
/// \endcond
|
/// \endcond
|
||||||
{ // clang-format on
|
{ // clang-format on
|
||||||
@ -75,138 +73,51 @@ class promise_base<Data, detail::identity<Args...>>
|
|||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor for constructing an empty promise
|
|
||||||
explicit promise_base() = default;
|
|
||||||
/// Constructor accepting the data object
|
/// Constructor accepting the data object
|
||||||
explicit promise_base(Data data) : data_(std::move(data)) {
|
explicit promise_base(Data data) : data_(std::move(data)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \cond false
|
|
||||||
promise_base(promise_base&&) = default;
|
|
||||||
promise_base(promise_base const&) = delete;
|
|
||||||
|
|
||||||
promise_base& operator=(promise_base&&) = default;
|
|
||||||
promise_base& operator=(promise_base const&) = delete;
|
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
/// Constructor accepting any object convertible to the data object
|
/// Constructor accepting any object convertible to the data object
|
||||||
template <typename OData,
|
template <typename OData, std::enable_if_t<std::is_convertible<
|
||||||
std::enable_if_t<std::is_convertible<
|
std::decay_t<OData>, Data>::value>* = nullptr>
|
||||||
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
promise_base(OData&& data) : data_(std::forward<OData>(data)) {
|
||||||
/* implicit */ promise_base(OData&& data) : data_(std::forward<OData>(data)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Assignment operator accepting any object convertible to the data object
|
|
||||||
template <typename OData,
|
|
||||||
std::enable_if_t<std::is_convertible<
|
|
||||||
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
|
||||||
promise_base& operator=(OData&& data) {
|
|
||||||
data_ = std::forward<OData>(data);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the continuation with the given values.
|
/// Resolves the continuation with the given values.
|
||||||
///
|
///
|
||||||
/// \throws This method never throws an exception.
|
/// \throws This method never throws an exception.
|
||||||
///
|
///
|
||||||
/// \attention This method may only be called once,
|
|
||||||
/// when the promise is valid operator bool() returns true.
|
|
||||||
/// Calling this method will invalidate the promise such that
|
|
||||||
/// subsequent calls to operator bool() will return false.
|
|
||||||
/// This behaviour is only consistent in promise_base and
|
|
||||||
/// non type erased promises may behave differently.
|
|
||||||
/// Invoking an invalid promise_base is undefined!
|
|
||||||
///
|
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
void operator()(Args... args) && noexcept {
|
void operator()(Args... args) && noexcept {
|
||||||
assert(data_);
|
|
||||||
std::move(data_)(std::move(args)...);
|
std::move(data_)(std::move(args)...);
|
||||||
data_ = nullptr;
|
|
||||||
}
|
}
|
||||||
/// Resolves the continuation with the given exception.
|
/// Resolves the continuation with the given exception.
|
||||||
///
|
///
|
||||||
/// \throws This method never throws an exception.
|
/// \throws This method never throws an exception.
|
||||||
///
|
///
|
||||||
/// \attention This method may only be called once,
|
|
||||||
/// when the promise is valid operator bool() returns true.
|
|
||||||
/// Calling this method will invalidate the promise such that
|
|
||||||
/// subsequent calls to operator bool() will return false.
|
|
||||||
/// This behaviour is only consistent in promise_base and
|
|
||||||
/// non type erased promises may behave differently.
|
|
||||||
/// Invoking an invalid promise_base is undefined!
|
|
||||||
///
|
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
void operator()(exception_arg_t tag, exception_t exception) && noexcept {
|
void operator()(detail::types::dispatch_error_tag tag,
|
||||||
assert(data_);
|
detail::types::error_type exception) &&
|
||||||
|
noexcept {
|
||||||
std::move(data_)(tag, std::move(exception));
|
std::move(data_)(tag, std::move(exception));
|
||||||
data_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the continuation with the given values.
|
/// Resolves the continuation with the given values.
|
||||||
///
|
///
|
||||||
/// \throws This method never throws an exception.
|
/// \throws This method never throws an exception.
|
||||||
///
|
///
|
||||||
/// \attention This method may only be called once,
|
|
||||||
/// when the promise is valid operator bool() returns true.
|
|
||||||
/// Calling this method will invalidate the promise such that
|
|
||||||
/// subsequent calls to operator bool() will return false.
|
|
||||||
/// This behaviour is only consistent in promise_base and
|
|
||||||
/// non type erased promises may behave differently.
|
|
||||||
/// Invoking an invalid promise_base is undefined!
|
|
||||||
///
|
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
void set_value(Args... args) noexcept {
|
void set_value(Args... args) noexcept {
|
||||||
// assert(data_);
|
|
||||||
std::move(data_)(std::move(args)...);
|
std::move(data_)(std::move(args)...);
|
||||||
data_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the continuation with the given exception.
|
/// Resolves the continuation with the given exception.
|
||||||
///
|
///
|
||||||
/// \throws This method never throws an exception.
|
/// \throws This method never throws an exception.
|
||||||
///
|
///
|
||||||
/// \attention This method may only be called once,
|
|
||||||
/// when the promise is valid operator bool() returns true.
|
|
||||||
/// Calling this method will invalidate the promise such that
|
|
||||||
/// subsequent calls to operator bool() will return false.
|
|
||||||
/// This behaviour is only consistent in promise_base and
|
|
||||||
/// non type erased promises may behave differently.
|
|
||||||
/// Invoking an invalid promise_base is undefined!
|
|
||||||
///
|
|
||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
void set_exception(exception_t exception) noexcept {
|
void set_exception(detail::types::error_type exception) noexcept {
|
||||||
assert(data_);
|
std::move(data_)(detail::types::dispatch_error_tag{}, std::move(exception));
|
||||||
std::move(data_)(exception_arg_t{}, std::move(exception));
|
|
||||||
data_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resolves the continuation with the cancellation token which is represented
|
|
||||||
/// by a default constructed exception_t.
|
|
||||||
///
|
|
||||||
/// \throws This method never throws an exception.
|
|
||||||
///
|
|
||||||
/// \attention This method may only be called once,
|
|
||||||
/// when the promise is valid operator bool() returns true.
|
|
||||||
/// Calling this method will invalidate the promise such that
|
|
||||||
/// subsequent calls to operator bool() will return false.
|
|
||||||
/// This behaviour is only consistent in promise_base and
|
|
||||||
/// non type erased promises may behave differently.
|
|
||||||
/// Invoking an invalid promise_base is undefined!
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
void set_canceled() noexcept {
|
|
||||||
assert(data_);
|
|
||||||
std::move(data_)(exception_arg_t{}, exception_t{});
|
|
||||||
data_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the continuation is valid (non empty).
|
|
||||||
///
|
|
||||||
/// \throws This method never throws an exception.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
return bool(data_);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/// \}
|
/// \}
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -33,7 +33,8 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/other/promisify.hpp>
|
|
||||||
|
#include <continuable/detail/promisify.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Promisify Promisify
|
/// \defgroup Promisify Promisify
|
||||||
@ -71,47 +72,18 @@ public:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// A given error variable is converted to the used error type.
|
/// If the error code which is passed as first parameter is set there are
|
||||||
/// If this isn't possible you need to create a custom resolver callable
|
/// two behaviours depending whether exceptions are enabled:
|
||||||
/// object \see with for details.
|
/// - If exceptions are enabled the error type is passed via
|
||||||
|
/// an exception_ptr to the failure handler.
|
||||||
|
/// - If exceptions are disabled the error type is converted to a
|
||||||
|
/// `std::error_conditon` and passed down to the error handler.
|
||||||
///
|
///
|
||||||
/// \since 3.0.0
|
/// \since 3.0.0
|
||||||
template <typename Callable, typename... Args>
|
template <typename Callable, typename... Args>
|
||||||
static auto from(Callable&& callable, Args&&... args) {
|
static auto from(Callable&& callable, Args&&... args) {
|
||||||
return helper::template from(detail::convert::default_resolver(),
|
return helper::template from<detail::convert::promisify_default>(
|
||||||
std::forward<Callable>(callable),
|
std::forward<Callable>(callable), std::forward<Args>(args)...);
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \copybrief from
|
|
||||||
///
|
|
||||||
/// This modification of \ref from additionally takes a resolver callable
|
|
||||||
/// object which is used to resolve the promise from the given result.
|
|
||||||
///
|
|
||||||
/// See an example of how to promisify boost asio's async_resolve below:
|
|
||||||
/// ```cpp
|
|
||||||
/// auto async_resolve(std::string host, std::string service) {
|
|
||||||
/// return cti::promisify<asio::ip::udp::resolver::iterator>::with(
|
|
||||||
/// [](auto&& promise, auto&& e, auto&&... args) {
|
|
||||||
/// if (e) {
|
|
||||||
/// promise.set_exception(std::forward<decltype(e)>(e));
|
|
||||||
/// } else {
|
|
||||||
/// promise.set_value(std::forward<decltype(args)>(args)...);
|
|
||||||
/// }
|
|
||||||
/// },
|
|
||||||
/// [&](auto&&... args) {
|
|
||||||
/// resolver_.async_resolve(std::forward<decltype(args)>(args)...);
|
|
||||||
/// },
|
|
||||||
/// std::move(host), std::move(service));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename Resolver, typename Callable, typename... Args>
|
|
||||||
static auto with(Resolver&& resolver, Callable&& callable, Args&&... args) {
|
|
||||||
return helper::template from(std::forward<Resolver>(resolver),
|
|
||||||
std::forward<Callable>(callable),
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/// \}
|
/// \}
|
||||||
|
|||||||
@ -1,356 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_RESULT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_RESULT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/utility/result-trait.hpp>
|
|
||||||
#include <continuable/detail/utility/result-variant.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \defgroup Result Result
|
|
||||||
/// provides the \ref result class and corresponding utility functions to work
|
|
||||||
/// with the result of an asynchronous operation which can possibly yield:
|
|
||||||
/// - *no result*: If the operation didn't finish
|
|
||||||
/// - *a value*: If the operation finished successfully
|
|
||||||
/// - *an exception*: If the operation finished with an exception
|
|
||||||
/// or was cancelled.
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// A tag which represents present void values in result.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
using void_arg_t = detail::void_arg_t;
|
|
||||||
|
|
||||||
/// A class which is convertible to any \ref result and that definitely holds no
|
|
||||||
/// value so the real result gets invalidated when this object is passed to it.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
struct empty_result {};
|
|
||||||
|
|
||||||
/// A class which is convertible to any \ref result and that definitely holds
|
|
||||||
/// a default constructed exception which signals the cancellation of the
|
|
||||||
/// asynchronous control flow.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
struct cancellation_result {};
|
|
||||||
|
|
||||||
/// A class which is convertible to any result and that holds
|
|
||||||
/// an exception which is then passed to the converted result object.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
class exceptional_result {
|
|
||||||
exception_t exception_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
exceptional_result() = delete;
|
|
||||||
exceptional_result(exceptional_result const&) = default;
|
|
||||||
exceptional_result(exceptional_result&&) = default;
|
|
||||||
exceptional_result& operator=(exceptional_result const&) = default;
|
|
||||||
exceptional_result& operator=(exceptional_result&&) = default;
|
|
||||||
~exceptional_result() = default;
|
|
||||||
|
|
||||||
explicit exceptional_result(exception_t exception)
|
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
|
|
||||||
: exception_(std::move(exception)) {}
|
|
||||||
|
|
||||||
exceptional_result& operator=(exception_t exception) {
|
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
|
|
||||||
exception_ = std::move(exception);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets an exception
|
|
||||||
void set_exception(exception_t exception) {
|
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
|
|
||||||
exception_ = std::move(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the contained exception
|
|
||||||
exception_t& get_exception() & noexcept {
|
|
||||||
return exception_;
|
|
||||||
}
|
|
||||||
/// \copydoc get_exception
|
|
||||||
exception_t const& get_exception() const& noexcept {
|
|
||||||
return exception_;
|
|
||||||
}
|
|
||||||
/// \copydoc get_exception
|
|
||||||
exception_t&& get_exception() && noexcept {
|
|
||||||
return std::move(exception_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The result class can carry the three kinds of results an asynchronous
|
|
||||||
/// operation possibly can return, it's implemented in a variant like
|
|
||||||
/// data structure which is also specialized to hold arbitrary arguments.
|
|
||||||
///
|
|
||||||
/// The result can be in the following three states:
|
|
||||||
/// - *no result*: If the operation didn't finish
|
|
||||||
/// - *a value*: If the operation finished successfully
|
|
||||||
/// - *an exception*: If the operation finished with an exception
|
|
||||||
/// or was cancelled.
|
|
||||||
///
|
|
||||||
/// The interface of the result object is similar to the one proposed in
|
|
||||||
/// the `std::expected` proposal:
|
|
||||||
/// ```cpp
|
|
||||||
/// result<std::string> result = make_result("Hello World!");
|
|
||||||
/// bool(result);
|
|
||||||
/// result.is_value();
|
|
||||||
/// result.is_exception();
|
|
||||||
/// *result; // Same as result.get_value()
|
|
||||||
/// result.get_value();
|
|
||||||
/// result.get_exception();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename... T>
|
|
||||||
class result {
|
|
||||||
using trait_t = detail::result_trait<T...>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
explicit result(detail::init_result_arg_t arg, Args&&... values)
|
|
||||||
: variant_(arg, trait_t::wrap(std::forward<Args>(values)...)) {}
|
|
||||||
explicit result(detail::init_exception_arg_t arg, exception_t exception)
|
|
||||||
: variant_(arg, std::move(exception)) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_t = typename trait_t::value_t;
|
|
||||||
using value_placeholder_t = typename trait_t::surrogate_t;
|
|
||||||
|
|
||||||
template <typename FirstArg, typename... Args>
|
|
||||||
explicit result(FirstArg&& first, Args&&... values)
|
|
||||||
: variant_(detail::init_result_arg_t{},
|
|
||||||
trait_t::wrap(std::forward<FirstArg>(first),
|
|
||||||
std::forward<Args>(values)...)) {}
|
|
||||||
|
|
||||||
result() = default;
|
|
||||||
result(result const&) = delete;
|
|
||||||
result(result&&) = default;
|
|
||||||
result& operator=(result const&) = delete;
|
|
||||||
result& operator=(result&&) = default;
|
|
||||||
~result() = default;
|
|
||||||
|
|
||||||
explicit result(exception_t exception)
|
|
||||||
: variant_(detail::init_exception_arg_t{}, std::move(exception)) {}
|
|
||||||
/* implicit */ result(empty_result) {}
|
|
||||||
/* implicit */ result(exceptional_result exceptional_result)
|
|
||||||
: variant_(detail::init_exception_arg_t{},
|
|
||||||
std::move(exceptional_result.get_exception())) {}
|
|
||||||
/* implicit */ result(cancellation_result)
|
|
||||||
: variant_(detail::init_exception_arg_t{}, exception_t{}) {}
|
|
||||||
|
|
||||||
result& operator=(empty_result) {
|
|
||||||
variant_.set_empty();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
result& operator=(value_placeholder_t value) {
|
|
||||||
variant_.set_value(std::move(value));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
result& operator=(exceptional_result exception) {
|
|
||||||
variant_.set_exception(std::move(exception.get_exception()));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
result& operator=(cancellation_result) {
|
|
||||||
variant_.set_exception({});
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the result to an empty state
|
|
||||||
void set_empty() {
|
|
||||||
variant_.set_empty();
|
|
||||||
}
|
|
||||||
/// Set the result to a the state which holds the corresponding value
|
|
||||||
void set_value(T... values) {
|
|
||||||
variant_.set_value(trait_t::wrap(std::move(values)...));
|
|
||||||
}
|
|
||||||
/// Set the result into a state which holds the corresponding exception
|
|
||||||
void set_exception(exception_t exception) {
|
|
||||||
variant_.set_exception(std::move(exception));
|
|
||||||
}
|
|
||||||
/// Set the result into a state which holds the cancellation token
|
|
||||||
void set_canceled() {
|
|
||||||
variant_.set_exception(exception_t{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the state of the result is empty
|
|
||||||
bool is_empty() const noexcept {
|
|
||||||
return variant_.is_empty();
|
|
||||||
}
|
|
||||||
/// Returns true if the state of the result holds the result
|
|
||||||
bool is_value() const noexcept {
|
|
||||||
return variant_.is_value();
|
|
||||||
}
|
|
||||||
/// Returns true if the state of the result holds a present exception
|
|
||||||
bool is_exception() const noexcept {
|
|
||||||
return variant_.is_exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \copydoc is_value
|
|
||||||
explicit constexpr operator bool() const noexcept {
|
|
||||||
return is_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the values of the result, if the result doesn't hold the value
|
|
||||||
/// the behaviour is undefined but will assert in debug mode.
|
|
||||||
decltype(auto) get_value() & noexcept {
|
|
||||||
return trait_t::unwrap(variant_.get_value());
|
|
||||||
}
|
|
||||||
///\copydoc get_value
|
|
||||||
decltype(auto) get_value() const& noexcept {
|
|
||||||
return trait_t::unwrap(variant_.get_value());
|
|
||||||
}
|
|
||||||
///\copydoc get_value
|
|
||||||
decltype(auto) get_value() && noexcept {
|
|
||||||
return trait_t::unwrap(std::move(variant_.get_value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
///\copydoc get_value
|
|
||||||
decltype(auto) operator*() & noexcept {
|
|
||||||
return get_value();
|
|
||||||
}
|
|
||||||
///\copydoc get_value
|
|
||||||
decltype(auto) operator*() const& noexcept {
|
|
||||||
return get_value();
|
|
||||||
}
|
|
||||||
///\copydoc get_value
|
|
||||||
decltype(auto) operator*() && noexcept {
|
|
||||||
return std::move(variant_.get_value());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the exception of the result, if the result doesn't hold an
|
|
||||||
/// exception the behaviour is undefined but will assert in debug mode.
|
|
||||||
exception_t& get_exception() & noexcept {
|
|
||||||
return variant_.get_exception();
|
|
||||||
}
|
|
||||||
/// \copydoc get_exception
|
|
||||||
exception_t const& get_exception() const& noexcept {
|
|
||||||
return variant_.get_exception();
|
|
||||||
}
|
|
||||||
/// \copydoc get_exception
|
|
||||||
exception_t&& get_exception() && noexcept {
|
|
||||||
return std::move(variant_.get_exception());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a present result from the given values
|
|
||||||
static result from(T... values) {
|
|
||||||
return result{detail::init_result_arg_t{}, std::move(values)...};
|
|
||||||
}
|
|
||||||
/// Creates a present result from the given exception
|
|
||||||
static result from(exception_arg_t, exception_t exception) {
|
|
||||||
return result{detail::init_exception_arg_t{}, std::move(exception)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an empty result
|
|
||||||
static result empty() {
|
|
||||||
return result{empty_result{}};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
detail::result_variant<value_placeholder_t> variant_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Returns the value at position I of the given result
|
|
||||||
template <std::size_t I, typename... T>
|
|
||||||
decltype(auto) get(result<T...>& result) {
|
|
||||||
return detail::result_trait<T...>::template get<I>(result);
|
|
||||||
}
|
|
||||||
/// \copydoc get
|
|
||||||
template <std::size_t I, typename... T>
|
|
||||||
decltype(auto) get(result<T...> const& result) {
|
|
||||||
return detail::result_trait<T...>::template get<I>(result);
|
|
||||||
}
|
|
||||||
/// \copydoc get
|
|
||||||
template <std::size_t I, typename... T>
|
|
||||||
decltype(auto) get(result<T...>&& result) {
|
|
||||||
return detail::result_trait<T...>::template get<I>(std::move(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a present result from the given values.
|
|
||||||
///
|
|
||||||
/// This could be used to pass the result of the next handler to the same
|
|
||||||
/// asynchronous path it came from as shown below:
|
|
||||||
/// ```cpp
|
|
||||||
/// make_ready_continuable().next([&](auto&&... args) {
|
|
||||||
/// result<> captured = make_result(std::forward<decltype(args)>(args)...);
|
|
||||||
/// return shutdown().then([captured = std::move(captured)]() mutable {
|
|
||||||
/// return std::move(captured);
|
|
||||||
/// });
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename... T,
|
|
||||||
typename Result = result<detail::traits::unrefcv_t<T>...>>
|
|
||||||
Result make_result(T&&... values) {
|
|
||||||
return Result::from(std::forward<T>(values)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an exceptional_result from the given exception.
|
|
||||||
///
|
|
||||||
/// \copydetails make_result
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
inline exceptional_result make_result(exception_arg_t, exception_t exception) {
|
|
||||||
// NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
|
|
||||||
return exceptional_result{std::move(exception)};
|
|
||||||
}
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
// The GCC standard library defines tuple_size as class and struct which
|
|
||||||
// triggers a warning here.
|
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma GCC diagnostic push
|
|
||||||
# pragma GCC diagnostic ignored "-Wmismatched-tags"
|
|
||||||
#endif
|
|
||||||
template <typename... Args>
|
|
||||||
struct tuple_size<cti::result<Args...>>
|
|
||||||
: std::integral_constant<size_t, sizeof...(Args)> {};
|
|
||||||
|
|
||||||
template <std::size_t I, typename... Args>
|
|
||||||
struct tuple_element<I, cti::result<Args...>>
|
|
||||||
: tuple_element<I, tuple<Args...>> {};
|
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_RESULT_HPP_INCLUDED
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,18 +21,18 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#ifndef CONTINUABLE_EXTERNAL_GTEST_HPP_INCLUDED
|
#ifndef CONTINUABLE_TESTING_HPP_INCLUDED
|
||||||
#define CONTINUABLE_EXTERNAL_GTEST_HPP_INCLUDED
|
#define CONTINUABLE_TESTING_HPP_INCLUDED
|
||||||
|
|
||||||
#include <continuable/detail/other/testing.hpp>
|
#include <continuable/detail/testing.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
/// \defgroup Testing Testing
|
/// \defgroup Testing Testing
|
||||||
/// provides macro shortcuts for testing asynchronous continuations through
|
/// provides macro shortcuts for testing asynchronous continuations through
|
||||||
@ -53,14 +53,6 @@
|
|||||||
#define ASSERT_ASYNC_EXCEPTION_COMPLETION(CONTINUABLE) \
|
#define ASSERT_ASYNC_EXCEPTION_COMPLETION(CONTINUABLE) \
|
||||||
cti::detail::testing::assert_async_exception_completion(CONTINUABLE);
|
cti::detail::testing::assert_async_exception_completion(CONTINUABLE);
|
||||||
|
|
||||||
/// Asserts that the final callback of the given continuable is called
|
|
||||||
/// with a cancelled result which is represented by a default constructed
|
|
||||||
/// exception_t.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
#define ASSERT_ASYNC_CANCELLATION(CONTINUABLE) \
|
|
||||||
cti::detail::testing::assert_async_cancellation(CONTINUABLE);
|
|
||||||
|
|
||||||
/// Asserts that the final callback of the given continuable is never called
|
/// Asserts that the final callback of the given continuable is never called
|
||||||
/// with any result.
|
/// with any result.
|
||||||
///
|
///
|
||||||
@ -166,7 +158,7 @@
|
|||||||
/// \since 1.0.0
|
/// \since 1.0.0
|
||||||
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
||||||
cti::detail::testing::assert_async_types( \
|
cti::detail::testing::assert_async_types( \
|
||||||
CONTINUABLE, cti::detail::identity<__VA_ARGS__>{})
|
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
||||||
|
|
||||||
/// Asserts that the continuable is finished with the given exception
|
/// Asserts that the continuable is finished with the given exception
|
||||||
///
|
///
|
||||||
@ -177,4 +169,4 @@
|
|||||||
|
|
||||||
/// \}
|
/// \}
|
||||||
|
|
||||||
#endif // CONTINUABLE_EXTERNAL_GTEST_HPP_INCLUDED
|
#endif // CONTINUABLE_TESTING_HPP_INCLUDED
|
||||||
80
include/continuable/continuable-trait.hpp
Normal file
80
include/continuable/continuable-trait.hpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <continuable/continuable-base.hpp>
|
||||||
|
#include <continuable/continuable-promise-base.hpp>
|
||||||
|
#include <continuable/detail/hints.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
/// \defgroup Types Types
|
||||||
|
/// provides the \link cti::continuable continuable\endlink and \link
|
||||||
|
/// cti::promise promise\endlink facility for type erasure.
|
||||||
|
/// \{
|
||||||
|
|
||||||
|
/// Trait to retrieve a continuable_base type with a given type-erasure backend.
|
||||||
|
///
|
||||||
|
/// Every object may me used as type-erasure backend as long as the
|
||||||
|
/// requirements of a `std::function` like wrapper are satisfied.
|
||||||
|
///
|
||||||
|
/// \tparam CallbackWrapper The type which is used to erase the callback.
|
||||||
|
///
|
||||||
|
/// \tparam ContinuationWrapper The type which is used to erase the
|
||||||
|
/// continuation data.
|
||||||
|
///
|
||||||
|
/// \tparam Args The current signature of the continuable.
|
||||||
|
template <template <std::size_t, typename...> class CallbackWrapper,
|
||||||
|
template <std::size_t, typename...> class ContinuationWrapper,
|
||||||
|
typename... Args>
|
||||||
|
class continuable_trait {
|
||||||
|
|
||||||
|
using callback = CallbackWrapper<0U, void(Args...)&&,
|
||||||
|
void(detail::types::dispatch_error_tag,
|
||||||
|
detail::types::error_type) &&>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The promise type which is used to resolve continuations
|
||||||
|
using promise =
|
||||||
|
promise_base<callback, detail::hints::signature_hint_tag<Args...>>;
|
||||||
|
|
||||||
|
/// The continuable type for the given parameters.
|
||||||
|
using continuable =
|
||||||
|
continuable_base<ContinuationWrapper<sizeof(callback), void(promise)>,
|
||||||
|
detail::hints::signature_hint_tag<Args...>>;
|
||||||
|
};
|
||||||
|
/// \}
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -31,8 +31,8 @@
|
|||||||
#ifndef CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
#ifndef CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
||||||
#define CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
#define CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
||||||
|
|
||||||
#include <continuable/transforms/wait.hpp>
|
#include <continuable/detail/transforms.hpp>
|
||||||
#include <continuable/transforms/future.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Transforms Transforms
|
/// \defgroup Transforms Transforms
|
||||||
@ -41,12 +41,70 @@ namespace cti {
|
|||||||
/// types such as (`std::future`).
|
/// types such as (`std::future`).
|
||||||
/// \{
|
/// \{
|
||||||
|
|
||||||
|
/// A callable tag object which marks a wrapped callable object
|
||||||
|
/// as continuable transformation which enables some useful overloads.
|
||||||
|
///
|
||||||
|
/// \since 3.0.0
|
||||||
|
template <typename T>
|
||||||
|
using transform = detail::types::transform<T>;
|
||||||
|
|
||||||
|
/// Wraps the given callable object into a transform class.
|
||||||
|
///
|
||||||
|
/// \since 3.0.0
|
||||||
|
template <typename T>
|
||||||
|
auto make_transform(T&& callable) {
|
||||||
|
return transform<std::decay_t<T>>(std::forward<T>(callable));
|
||||||
|
}
|
||||||
|
|
||||||
/// The namespace transforms declares callable objects that transform
|
/// The namespace transforms declares callable objects that transform
|
||||||
/// any continuable_base to an object or to a continuable_base itself.
|
/// any continuable_base to an object or to a continuable_base itself.
|
||||||
///
|
///
|
||||||
/// Transforms can be applied to continuables through using
|
/// Transforms can be applied to continuables through using
|
||||||
/// the cti::continuable_base::apply method accordingly.
|
/// the cti::continuable_base::apply method accordingly.
|
||||||
namespace transforms {}
|
namespace transforms {
|
||||||
|
/// Returns a transform that if applied to a continuable,
|
||||||
|
/// it will start the continuation chain and returns the asynchronous
|
||||||
|
/// result as `std::future<...>`.
|
||||||
|
///
|
||||||
|
/// \returns Returns a `std::future<...>` which becomes ready as soon
|
||||||
|
/// as the the continuation chain has finished.
|
||||||
|
/// The signature of the future depends on the result type:
|
||||||
|
/// | Continuation type | Return type |
|
||||||
|
/// | : ------------------------------- | : -------------------------------- |
|
||||||
|
/// | `continuable_base with <>` | `std::future<void>` |
|
||||||
|
/// | `continuable_base with <Arg>` | `std::future<Arg>` |
|
||||||
|
/// | `continuable_base with <Args...>` | `std::future<std::tuple<Args...>>` |
|
||||||
|
///
|
||||||
|
/// \attention If exceptions are used, exceptions that are thrown, are forwarded
|
||||||
|
/// to the returned future. If there are no exceptions supported,
|
||||||
|
/// you shall not pass any errors to the end of the asynchronous
|
||||||
|
/// call chain!
|
||||||
|
/// Otherwise this will yield a trap that causes application exit.
|
||||||
|
///
|
||||||
|
/// \since 2.0.0
|
||||||
|
inline auto futurize() {
|
||||||
|
return make_transform([](auto&& continuable) {
|
||||||
|
using detail::transforms::as_future;
|
||||||
|
return as_future(std::forward<decltype(continuable)>(continuable));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a transform that if applied to a continuable, it will ignores all
|
||||||
|
/// error which ocured until the point the transform was applied.
|
||||||
|
///
|
||||||
|
/// \returns Returns a continuable with the same signature as applied to.
|
||||||
|
///
|
||||||
|
/// \attention This can be used to create a continuable which doesn't resolve
|
||||||
|
/// the continuation on errors.
|
||||||
|
///
|
||||||
|
/// \since 2.0.0
|
||||||
|
inline auto flatten() {
|
||||||
|
return make_transform([](auto&& continuable) {
|
||||||
|
return std::forward<decltype(continuable)>(continuable).fail([](auto&&) {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// \}
|
||||||
|
} // namespace transforms
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
#endif // CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
#endif // CONTINUABLE_TRANSFORMS_HPP_INCLUDED
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -32,7 +32,8 @@
|
|||||||
#define CONTINUABLE_TRAVERSE_ASYNC_HPP_INCLUDED
|
#define CONTINUABLE_TRAVERSE_ASYNC_HPP_INCLUDED
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/traversal/traverse-async.hpp>
|
|
||||||
|
#include <continuable/detail/traverse-async.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Traversal Traversal
|
/// \defgroup Traversal Traversal
|
||||||
@ -74,7 +75,7 @@ using async_traverse_in_place_tag =
|
|||||||
/// ```cpp
|
/// ```cpp
|
||||||
/// struct my_async_visitor {
|
/// struct my_async_visitor {
|
||||||
/// /// The synchronous overload is called for each object,
|
/// /// The synchronous overload is called for each object,
|
||||||
/// /// it may return false to suspend the current control flow.
|
/// /// it may return false to suspend the current control.
|
||||||
/// /// In that case the overload below is called.
|
/// /// In that case the overload below is called.
|
||||||
/// template <typename T>
|
/// template <typename T>
|
||||||
/// bool operator()(async_traverse_visit_tag, T&& element) {
|
/// bool operator()(async_traverse_visit_tag, T&& element) {
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -34,7 +34,8 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/traversal/traverse.hpp>
|
|
||||||
|
#include <continuable/detail/traverse.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Traversal Traversal
|
/// \defgroup Traversal Traversal
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -31,11 +31,11 @@
|
|||||||
#ifndef CONTINUABLE_TYPES_HPP_INCLUDED
|
#ifndef CONTINUABLE_TYPES_HPP_INCLUDED
|
||||||
#define CONTINUABLE_TYPES_HPP_INCLUDED
|
#define CONTINUABLE_TYPES_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <function2/function2.hpp>
|
#include <function2/function2.hpp>
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
#include <continuable/continuable-trait.hpp>
|
||||||
#include <continuable/continuable-promise-base.hpp>
|
|
||||||
#include <continuable/detail/other/erasure.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
/// \defgroup Types Types
|
/// \defgroup Types Types
|
||||||
@ -43,59 +43,48 @@ namespace cti {
|
|||||||
/// cti::promise promise\endlink facility for type erasure.
|
/// cti::promise promise\endlink facility for type erasure.
|
||||||
/// \{
|
/// \{
|
||||||
|
|
||||||
/// Deduces to the preferred continuation capacity for a possible
|
// clang-format off
|
||||||
/// small functor optimization. The given capacity size is always enough to
|
namespace detail {
|
||||||
/// to avoid any allocation when storing a ready continuable_base.
|
/// A function which isn't size adjusted and move only
|
||||||
///
|
template<std::size_t, typename... Args>
|
||||||
/// \since 4.0.0
|
using unique_function_adapter = fu2::unique_function<Args...>;
|
||||||
template <typename... Args>
|
/// A function which is size adjusted and move only
|
||||||
using continuation_capacity = detail::erasure::continuation_capacity<Args...>;
|
template<std::size_t Size, typename... Args>
|
||||||
|
using unique_function_adjustable = fu2::function_base<true, false, Size,
|
||||||
|
true, false, Args...>;
|
||||||
|
|
||||||
|
/// We adjust the internal capacity of the outer function wrapper so
|
||||||
|
/// we don't have to allocate twice when using `continuable<...>`.
|
||||||
|
template<typename... Args>
|
||||||
|
using unique_trait_of = continuable_trait<
|
||||||
|
unique_function_adapter,
|
||||||
|
unique_function_adjustable,
|
||||||
|
Args...
|
||||||
|
>;
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// Defines a non-copyable continuation type which uses the
|
/// Defines a non-copyable continuation type which uses the
|
||||||
/// function2 backend for type erasure.
|
/// function2 backend for type erasure.
|
||||||
///
|
///
|
||||||
/// Usable like: `continuable<int, float>`
|
/// Usable like: `continuable<int, float>`
|
||||||
///
|
|
||||||
/// \note You can always define your own continuable with a type erasure of
|
|
||||||
/// choice, the type erasure wrapper just needs to accept a
|
|
||||||
/// callable object with a continuation signature as specified
|
|
||||||
/// in the Primitives section.
|
|
||||||
///
|
|
||||||
/// \since 1.0.0
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using continuable = continuable_base<detail::erasure::continuation<Args...>, //
|
using continuable = typename detail::unique_trait_of<
|
||||||
signature_arg_t<Args...>>;
|
Args...
|
||||||
|
>::continuable;
|
||||||
|
|
||||||
/// Defines a non-copyable promise type which is using the
|
/// Defines a non-copyable promise type which is using the
|
||||||
/// function2 backend for type erasure.
|
/// function2 backend for type erasure.
|
||||||
///
|
///
|
||||||
/// Usable like: `promise<int, float>`
|
/// Usable like: `promise<int, float>`
|
||||||
///
|
|
||||||
/// \note You can always define your own promise with a type erasure of
|
|
||||||
/// choice, the type erasure wrapper just needs to accept a
|
|
||||||
/// callable object with a callback signature as specified
|
|
||||||
/// in the Primitives section.
|
|
||||||
///
|
|
||||||
/// \since 1.0.0
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
using promise = promise_base<detail::erasure::callback<Args...>, //
|
using promise = typename detail::unique_trait_of<
|
||||||
signature_arg_t<Args...>>;
|
Args...
|
||||||
|
>::promise;
|
||||||
|
|
||||||
/// Defines a non-copyable type erasure which is capable of carrying
|
// TODO channel
|
||||||
/// callable objects passed to executors.
|
// TODO sink
|
||||||
///
|
|
||||||
/// The work behaves like a `promise<>` but the work type erasure uses extra
|
// clang-format on
|
||||||
/// stack space for small object optimization.
|
|
||||||
/// Additionally the outstanding work can be resolved through an exception.
|
|
||||||
///
|
|
||||||
/// \note You can always define your own cancelable_work with a type erasure of
|
|
||||||
/// choice, the type erasure wrapper just needs to accept a
|
|
||||||
/// callable object which is callable with a `void()` and
|
|
||||||
/// `void(exception_arg_t, exception_t)` signature.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
using work = promise_base<detail::erasure::work, //
|
|
||||||
signature_arg_t<>>;
|
|
||||||
/// \}
|
/// \}
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -47,12 +47,9 @@ namespace cti {}
|
|||||||
|
|
||||||
#include <continuable/continuable-base.hpp>
|
#include <continuable/continuable-base.hpp>
|
||||||
#include <continuable/continuable-connections.hpp>
|
#include <continuable/continuable-connections.hpp>
|
||||||
#include <continuable/continuable-coroutine.hpp>
|
|
||||||
#include <continuable/continuable-operations.hpp>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-promise-base.hpp>
|
#include <continuable/continuable-promise-base.hpp>
|
||||||
#include <continuable/continuable-promisify.hpp>
|
#include <continuable/continuable-promisify.hpp>
|
||||||
#include <continuable/continuable-result.hpp>
|
#include <continuable/continuable-trait.hpp>
|
||||||
#include <continuable/continuable-transforms.hpp>
|
#include <continuable/continuable-transforms.hpp>
|
||||||
#include <continuable/continuable-traverse-async.hpp>
|
#include <continuable/continuable-traverse-async.hpp>
|
||||||
#include <continuable/continuable-traverse.hpp>
|
#include <continuable/continuable-traverse.hpp>
|
||||||
|
|||||||
144
include/continuable/detail/awaiting.hpp
Normal file
144
include/continuable/detail/awaiting.hpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
// Exclude this header when coroutines are not available
|
||||||
|
#ifndef CONTINUABLE_DETAIL_AWAITING_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_AWAITING_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
|
||||||
|
#include <continuable/detail/expected.hpp>
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/hints.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
#include <exception>
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace awaiting {
|
||||||
|
/// We import the coroutine handle in our namespace
|
||||||
|
using std::experimental::coroutine_handle;
|
||||||
|
|
||||||
|
/// An object which provides the internal buffer and helper methods
|
||||||
|
/// for waiting on a continuable in a stackless coroutine.
|
||||||
|
template <typename Continuable>
|
||||||
|
class awaitable {
|
||||||
|
using trait_t = container::expected_result_trait_t<Continuable>;
|
||||||
|
|
||||||
|
/// The continuable which is invoked upon suspension
|
||||||
|
Continuable continuable_;
|
||||||
|
/// A cache which is used to pass the result of the continuation
|
||||||
|
/// to the coroutine.
|
||||||
|
typename trait_t::expected_type result_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit constexpr awaitable(Continuable&& continuable)
|
||||||
|
: continuable_(std::move(continuable)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Since continuables are evaluated lazily we are not
|
||||||
|
/// capable to say whether the resumption will be instantly.
|
||||||
|
bool await_ready() const noexcept {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Suspend the current context
|
||||||
|
// TODO Convert this to an r-value function once possible
|
||||||
|
void await_suspend(coroutine_handle<> h) {
|
||||||
|
// Forward every result to the current awaitable
|
||||||
|
std::move(continuable_)
|
||||||
|
.next([h, this](auto&&... args) mutable {
|
||||||
|
resolve(std::forward<decltype(args)>(args)...);
|
||||||
|
h.resume();
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resume the coroutine represented by the handle
|
||||||
|
auto await_resume() noexcept(false) {
|
||||||
|
if (result_) {
|
||||||
|
// When the result was resolved return it
|
||||||
|
return trait_t::unwrap(std::move(result_));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
std::rethrow_exception(result_.get_exception());
|
||||||
|
#else // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
// Returning error types in await isn't supported as of now
|
||||||
|
util::trap();
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Resolve the continuation through the result
|
||||||
|
template <typename... Args>
|
||||||
|
void resolve(Args&&... args) {
|
||||||
|
result_.set_value(trait_t::wrap(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve the continuation through an error
|
||||||
|
void resolve(types::dispatch_error_tag, types::error_type error) {
|
||||||
|
result_.set_exception(std::move(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Converts a continuable into an awaitable object as described by
|
||||||
|
/// the C++ coroutine TS.
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto create_awaiter(T&& continuable) {
|
||||||
|
return awaitable<std::decay_t<T>>(std::forward<T>(continuable));
|
||||||
|
}
|
||||||
|
} // namespace awaiting
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
// As far as I know there is no other was to implement this specialization...
|
||||||
|
// NOLINTNEXTLINE(cert-dcl58-cpp)
|
||||||
|
namespace std {
|
||||||
|
namespace experimental {
|
||||||
|
template <typename Data, typename... Args, typename... FunctionArgs>
|
||||||
|
struct coroutine_traits<
|
||||||
|
cti::continuable_base<Data,
|
||||||
|
cti::detail::hints::signature_hint_tag<Args...>>,
|
||||||
|
FunctionArgs...> {
|
||||||
|
|
||||||
|
static_assert(cti::detail::traits::fail<Data>::value,
|
||||||
|
"Using a continuable as return type from co_return "
|
||||||
|
"expressions isn't supported yet!");
|
||||||
|
};
|
||||||
|
} // namespace experimental
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
||||||
593
include/continuable/detail/base.hpp
Normal file
593
include/continuable/detail/base.hpp
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_BASE_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_BASE_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
#include <continuable/detail/hints.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
#include <exception>
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
/// The namespace `base` provides the low level API for working
|
||||||
|
/// with continuable types.
|
||||||
|
///
|
||||||
|
/// Important methods are:
|
||||||
|
/// - Creating a continuation from a callback taking functional
|
||||||
|
/// base::attorney::create(auto&& callback)
|
||||||
|
/// -> base::continuation<auto>
|
||||||
|
/// - Chaining a continuation together with a callback
|
||||||
|
/// base::chain_continuation(base::continuation<auto> continuation,
|
||||||
|
/// auto&& callback)
|
||||||
|
/// -> base::continuation<auto>
|
||||||
|
/// - Finally invoking the continuation chain
|
||||||
|
/// base::finalize_continuation(base::continuation<auto> continuation)
|
||||||
|
/// -> void
|
||||||
|
namespace base {
|
||||||
|
template <typename T>
|
||||||
|
struct is_continuable : std::false_type {};
|
||||||
|
template <typename Data, typename Annotation>
|
||||||
|
struct is_continuable<continuable_base<Data, Annotation>> : std::true_type {};
|
||||||
|
|
||||||
|
/// Helper class to access private methods and members of
|
||||||
|
/// the continuable_base class.
|
||||||
|
struct attorney {
|
||||||
|
/// Makes a continuation wrapper from the given argument
|
||||||
|
template <typename T, typename A>
|
||||||
|
static auto create(T&& continuation, A /*hint*/, util::ownership ownership_) {
|
||||||
|
return continuable_base<std::decay_t<T>, std::decay_t<A>>(
|
||||||
|
std::forward<T>(continuation), ownership_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invokes a continuation object in a reference correct way
|
||||||
|
template <typename Data, typename Annotation, typename Callback>
|
||||||
|
static auto
|
||||||
|
invoke_continuation(continuable_base<Data, Annotation>&& continuation,
|
||||||
|
Callback&& callback) noexcept {
|
||||||
|
auto materialized = std::move(continuation).materialize();
|
||||||
|
materialized.release();
|
||||||
|
return materialized.data_(std::forward<Callback>(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Data, typename Annotation>
|
||||||
|
static auto materialize(continuable_base<Data, Annotation>&& continuation) {
|
||||||
|
return std::move(continuation).materialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Data, typename Annotation>
|
||||||
|
static Data&&
|
||||||
|
consume_data(continuable_base<Data, Annotation>&& continuation) {
|
||||||
|
return std::move(continuation).consume_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Continuable>
|
||||||
|
static util::ownership ownership_of(Continuable&& continuation) noexcept {
|
||||||
|
return continuation.ownership_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the invoker of a callback, the next callback
|
||||||
|
// and the arguments of the previous continuation.
|
||||||
|
//
|
||||||
|
// The return type of the invokerOf function matches a callable of:
|
||||||
|
// void(auto&& callback, auto&& next_callback, auto&&... args)
|
||||||
|
//
|
||||||
|
// The invoker decorates the result type in the following way
|
||||||
|
// - void -> next_callback()
|
||||||
|
// - ? -> next_callback(?)
|
||||||
|
// - std::pair<?, ?> -> next_callback(?, ?)
|
||||||
|
// - std::tuple<?...> -> next_callback(?...)
|
||||||
|
//
|
||||||
|
// When the result is a continuation itself pass the callback to it
|
||||||
|
// - continuation<?...> -> result(next_callback);
|
||||||
|
namespace decoration {
|
||||||
|
/// Helper class wrapping the underlaying unwrapping lambda
|
||||||
|
/// in order to extend it with a hint method.
|
||||||
|
template <typename T, typename Hint>
|
||||||
|
class invoker : public T {
|
||||||
|
public:
|
||||||
|
constexpr explicit invoker(T invoke) : T(std::move(invoke)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
using T::operator();
|
||||||
|
|
||||||
|
/// Returns the underlaying signature hint
|
||||||
|
static constexpr Hint hint() noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
#define CONTINUABLE_BLOCK_TRY_BEGIN try {
|
||||||
|
#define CONTINUABLE_BLOCK_TRY_END \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
std::forward<decltype(next_callback)>(next_callback)( \
|
||||||
|
types::dispatch_error_tag{}, std::current_exception()); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
#define CONTINUABLE_BLOCK_TRY_BEGIN {
|
||||||
|
#define CONTINUABLE_BLOCK_TRY_END }
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
/// Invokes the given callable object with the given arguments while
|
||||||
|
/// marking the operation as non exceptional.
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr auto invoke_no_except(T&& callable, Args&&... args) noexcept {
|
||||||
|
return std::forward<T>(callable)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr auto make_invoker(T&& invoke, hints::signature_hint_tag<Args...>) {
|
||||||
|
return invoker<std::decay_t<T>, hints::signature_hint_tag<Args...>>(
|
||||||
|
std::forward<T>(invoke));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// - continuable<?...> -> result(next_callback);
|
||||||
|
template <typename Data, typename Annotation>
|
||||||
|
constexpr auto
|
||||||
|
invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||||
|
/// Get the hint of the unwrapped returned continuable
|
||||||
|
using Type = decltype(attorney::materialize(
|
||||||
|
std::declval<continuable_base<Data, Annotation>>()));
|
||||||
|
|
||||||
|
auto constexpr const hint = hints::hint_of(traits::identify<Type>{});
|
||||||
|
|
||||||
|
return make_invoker(
|
||||||
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
|
auto continuation_ =
|
||||||
|
util::partial_invoke(std::forward<decltype(callback)>(callback),
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
|
attorney::invoke_continuation(
|
||||||
|
std::move(continuation_),
|
||||||
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
|
},
|
||||||
|
hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// - ? -> next_callback(?)
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto invoker_of(traits::identity<T>) {
|
||||||
|
return make_invoker(
|
||||||
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
|
auto result =
|
||||||
|
util::partial_invoke(std::forward<decltype(callback)>(callback),
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
|
invoke_no_except(std::forward<decltype(next_callback)>(next_callback),
|
||||||
|
std::move(result));
|
||||||
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
|
},
|
||||||
|
traits::identify<T>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// - void -> next_callback()
|
||||||
|
inline auto invoker_of(traits::identity<void>) {
|
||||||
|
return make_invoker(
|
||||||
|
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
|
util::partial_invoke(std::forward<decltype(callback)>(callback),
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
|
invoke_no_except(
|
||||||
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
|
},
|
||||||
|
traits::identity<>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a sequenced invoker which is able to invoke
|
||||||
|
/// objects where std::get is applicable.
|
||||||
|
inline auto sequenced_unpack_invoker() {
|
||||||
|
return [](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||||
|
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
|
auto result =
|
||||||
|
util::partial_invoke(std::forward<decltype(callback)>(callback),
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
|
// Workaround for MSVC not capturing the reference correctly inside
|
||||||
|
// the lambda.
|
||||||
|
using Next = decltype(next_callback);
|
||||||
|
|
||||||
|
traits::unpack(std::move(result), [&](auto&&... types) {
|
||||||
|
/// TODO Add inplace resolution here
|
||||||
|
|
||||||
|
invoke_no_except(std::forward<Next>(next_callback),
|
||||||
|
std::forward<decltype(types)>(types)...);
|
||||||
|
});
|
||||||
|
CONTINUABLE_BLOCK_TRY_END
|
||||||
|
};
|
||||||
|
} // namespace decoration
|
||||||
|
|
||||||
|
// - std::pair<?, ?> -> next_callback(?, ?)
|
||||||
|
template <typename First, typename Second>
|
||||||
|
constexpr auto invoker_of(traits::identity<std::pair<First, Second>>) {
|
||||||
|
return make_invoker(sequenced_unpack_invoker(),
|
||||||
|
traits::identity<First, Second>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// - std::tuple<?...> -> next_callback(?...)
|
||||||
|
template <typename... Args>
|
||||||
|
constexpr auto invoker_of(traits::identity<std::tuple<Args...>>) {
|
||||||
|
return make_invoker(sequenced_unpack_invoker(), traits::identity<Args...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CONTINUABLE_BLOCK_TRY_BEGIN
|
||||||
|
#undef CONTINUABLE_BLOCK_TRY_END
|
||||||
|
} // namespace decoration
|
||||||
|
|
||||||
|
/// Invoke the callback immediately
|
||||||
|
template <typename Invoker, typename... Args>
|
||||||
|
void packed_dispatch(types::this_thread_executor_tag, Invoker&& invoker,
|
||||||
|
Args&&... args) {
|
||||||
|
|
||||||
|
// Invoke the callback with the decorated invoker immediately
|
||||||
|
std::forward<Invoker>(invoker)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invoke the callback through the given executor
|
||||||
|
template <typename Executor, typename Invoker, typename... Args>
|
||||||
|
void packed_dispatch(Executor&& executor, Invoker&& invoker, Args&&... args) {
|
||||||
|
|
||||||
|
// Create a worker object which when invoked calls the callback with the
|
||||||
|
// the returned arguments.
|
||||||
|
auto work = [
|
||||||
|
invoker = std::forward<Invoker>(invoker),
|
||||||
|
args = std::make_tuple(std::forward<Args>(args)...)
|
||||||
|
]() mutable {
|
||||||
|
traits::unpack(std::move(args), [&](auto&&... captured_args) {
|
||||||
|
// Just use the packed dispatch method which dispatches the work on
|
||||||
|
// the current thread.
|
||||||
|
packed_dispatch(types::this_thread_executor_tag{}, std::move(invoker),
|
||||||
|
std::forward<decltype(captured_args)>(captured_args)...);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pass the work callable object to the executor
|
||||||
|
std::forward<Executor>(executor)(std::move(work));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tells whether we potentially move the chain upwards and handle the result
|
||||||
|
enum class handle_results {
|
||||||
|
no, //< The result is forwarded to the next callable
|
||||||
|
yes //< The result is handled by the current callable
|
||||||
|
};
|
||||||
|
|
||||||
|
// Silences a doxygen bug, it tries to map forward to std::forward
|
||||||
|
/// \cond false
|
||||||
|
/// Tells whether we handle the error through the callback
|
||||||
|
enum class handle_errors {
|
||||||
|
no, //< The error is forwarded to the next callable
|
||||||
|
plain, //< The error is the only argument accepted by the callable
|
||||||
|
forward //< The error is forwarded to the callable while keeping its tag
|
||||||
|
};
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
namespace callbacks {
|
||||||
|
namespace proto {
|
||||||
|
template <handle_results HandleResults, typename Base, typename Hint>
|
||||||
|
struct result_handler_base;
|
||||||
|
template <typename Base, typename... Args>
|
||||||
|
struct result_handler_base<handle_results::no, Base,
|
||||||
|
hints::signature_hint_tag<Args...>> {
|
||||||
|
void operator()(Args... args) && {
|
||||||
|
// Forward the arguments to the next callback
|
||||||
|
std::move(static_cast<Base*>(this)->next_callback_)(std::move(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename Base, typename... Args>
|
||||||
|
struct result_handler_base<handle_results::yes, Base,
|
||||||
|
hints::signature_hint_tag<Args...>> {
|
||||||
|
/// The operator which is called when the result was provided
|
||||||
|
void operator()(Args... args) && {
|
||||||
|
// In order to retrieve the correct decorator we must know what the
|
||||||
|
// result type is.
|
||||||
|
auto result = traits::identify<decltype(util::partial_invoke(
|
||||||
|
std::move(static_cast<Base*>(this)->callback_), std::move(args)...))>{};
|
||||||
|
|
||||||
|
// Pick the correct invoker that handles decorating of the result
|
||||||
|
auto invoker = decoration::invoker_of(result);
|
||||||
|
|
||||||
|
// Invoke the callback
|
||||||
|
packed_dispatch(std::move(static_cast<Base*>(this)->executor_),
|
||||||
|
std::move(invoker),
|
||||||
|
std::move(static_cast<Base*>(this)->callback_),
|
||||||
|
std::move(static_cast<Base*>(this)->next_callback_),
|
||||||
|
std::move(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto make_error_invoker(
|
||||||
|
std::integral_constant<handle_errors, handle_errors::plain>) noexcept {
|
||||||
|
return [](auto&& callback, types::error_type&& error) {
|
||||||
|
// Errors are not partial invoked
|
||||||
|
// NOLINTNEXTLINE(hicpp-move-const-arg)
|
||||||
|
std::forward<decltype(callback)>(callback)(std::move(error));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
inline auto make_error_invoker(
|
||||||
|
std::integral_constant<handle_errors, handle_errors::forward>) noexcept {
|
||||||
|
return [](auto&& callback, types::error_type&& error) {
|
||||||
|
// Errors are not partial invoked
|
||||||
|
std::forward<decltype(callback)>(callback)(
|
||||||
|
types::dispatch_error_tag{},
|
||||||
|
std::move(error)); // NOLINT(hicpp-move-const-arg)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <handle_errors HandleErrors /* = plain or forward*/, typename Base>
|
||||||
|
struct error_handler_base {
|
||||||
|
void operator()(types::dispatch_error_tag, types::error_type error) && {
|
||||||
|
// Just invoke the error handler, cancel the calling hierarchy after
|
||||||
|
auto invoker = make_error_invoker(
|
||||||
|
std::integral_constant<handle_errors, HandleErrors>{});
|
||||||
|
|
||||||
|
// Invoke the error handler
|
||||||
|
packed_dispatch(
|
||||||
|
std::move(static_cast<Base*>(this)->executor_), std::move(invoker),
|
||||||
|
std::move(static_cast<Base*>(this)->callback_), std::move(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename Base>
|
||||||
|
struct error_handler_base<handle_errors::no, Base> {
|
||||||
|
/// The operator which is called when an error occurred
|
||||||
|
void operator()(types::dispatch_error_tag tag, types::error_type error) && {
|
||||||
|
// Forward the error to the next callback
|
||||||
|
std::move(static_cast<Base*>(this)->next_callback_)(tag, std::move(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace proto
|
||||||
|
|
||||||
|
template <typename Hint, handle_results HandleResults,
|
||||||
|
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||||
|
typename NextCallback>
|
||||||
|
struct callback_base;
|
||||||
|
|
||||||
|
template <typename... Args, handle_results HandleResults,
|
||||||
|
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||||
|
typename NextCallback>
|
||||||
|
struct callback_base<hints::signature_hint_tag<Args...>, HandleResults,
|
||||||
|
HandleErrors, Callback, Executor, NextCallback>
|
||||||
|
: proto::result_handler_base<
|
||||||
|
HandleResults,
|
||||||
|
callback_base<hints::signature_hint_tag<Args...>, HandleResults,
|
||||||
|
HandleErrors, Callback, Executor, NextCallback>,
|
||||||
|
hints::signature_hint_tag<Args...>>,
|
||||||
|
proto::error_handler_base<
|
||||||
|
HandleErrors,
|
||||||
|
callback_base<hints::signature_hint_tag<Args...>, HandleResults,
|
||||||
|
HandleErrors, Callback, Executor, NextCallback>>,
|
||||||
|
util::non_copyable {
|
||||||
|
|
||||||
|
Callback callback_;
|
||||||
|
Executor executor_;
|
||||||
|
NextCallback next_callback_;
|
||||||
|
|
||||||
|
explicit callback_base(Callback callback, Executor executor,
|
||||||
|
NextCallback next_callback)
|
||||||
|
: callback_(std::move(callback)), executor_(std::move(executor)),
|
||||||
|
next_callback_(std::move(next_callback)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pull the result handling operator() in
|
||||||
|
using proto::result_handler_base<
|
||||||
|
HandleResults,
|
||||||
|
callback_base<hints::signature_hint_tag<Args...>, HandleResults,
|
||||||
|
HandleErrors, Callback, Executor, NextCallback>,
|
||||||
|
hints::signature_hint_tag<Args...>>::operator();
|
||||||
|
|
||||||
|
/// Pull the error handling operator() in
|
||||||
|
using proto::error_handler_base<
|
||||||
|
HandleErrors,
|
||||||
|
callback_base<hints::signature_hint_tag<Args...>, HandleResults,
|
||||||
|
HandleErrors, Callback, Executor, NextCallback>>::
|
||||||
|
operator();
|
||||||
|
|
||||||
|
/// Resolves the continuation with the given values
|
||||||
|
void set_value(Args... args) {
|
||||||
|
std::move (*this)(std::move(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves the continuation with the given error variable.
|
||||||
|
void set_exception(types::error_type error) {
|
||||||
|
std::move (*this)(types::dispatch_error_tag{}, std::move(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Hint, handle_results HandleResults,
|
||||||
|
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||||
|
typename NextCallback>
|
||||||
|
auto make_callback(Callback&& callback, Executor&& executor,
|
||||||
|
NextCallback&& next_callback) {
|
||||||
|
return callback_base<Hint, HandleResults, HandleErrors,
|
||||||
|
std::decay_t<Callback>, std::decay_t<Executor>,
|
||||||
|
std::decay_t<NextCallback>>{
|
||||||
|
std::forward<Callback>(callback), std::forward<Executor>(executor),
|
||||||
|
std::forward<NextCallback>(next_callback)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Once this was a workaround for GCC bug:
|
||||||
|
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
||||||
|
struct final_callback : util::non_copyable {
|
||||||
|
template <typename... Args>
|
||||||
|
void operator()(Args... /*args*/) && {
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::dispatch_error_tag, types::error_type error) && {
|
||||||
|
(void)error;
|
||||||
|
#ifndef CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
|
||||||
|
// There were unhandled errors inside the asynchronous call chain!
|
||||||
|
// Define `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` in order
|
||||||
|
// to ignore unhandled errors!"
|
||||||
|
util::trap();
|
||||||
|
#endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void set_value(Args... args) {
|
||||||
|
std::move (*this)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_exception(types::error_type error) {
|
||||||
|
// NOLINTNEXTLINE(hicpp-move-const-arg)
|
||||||
|
std::move (*this)(types::dispatch_error_tag{}, std::move(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace callbacks
|
||||||
|
|
||||||
|
/// Returns the next hint when the callback is invoked with the given hint
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr auto
|
||||||
|
next_hint_of(std::integral_constant<handle_results, handle_results::yes>,
|
||||||
|
traits::identity<T> /*callback*/,
|
||||||
|
hints::signature_hint_tag<Args...> /*current*/) {
|
||||||
|
// Partial Invoke the given callback
|
||||||
|
using Result = decltype(
|
||||||
|
util::partial_invoke(std::declval<T>(), std::declval<Args>()...));
|
||||||
|
|
||||||
|
// Return the hint of thr given invoker
|
||||||
|
return decltype(decoration::invoker_of(traits::identify<Result>{}).hint()){};
|
||||||
|
}
|
||||||
|
/// Don't progress the hint when we don't continue
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr auto
|
||||||
|
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
|
||||||
|
traits::identity<T> /*callback*/,
|
||||||
|
hints::signature_hint_tag<Args...> current) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Chains a callback together with a continuation and returns a continuation:
|
||||||
|
///
|
||||||
|
/// For example given:
|
||||||
|
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||||
|
/// - Callback: [](std::string) { }
|
||||||
|
///
|
||||||
|
/// This function returns a function accepting the next callback in the chain:
|
||||||
|
/// - Result: continuation<[](auto&& callback) { /*...*/ }>
|
||||||
|
///
|
||||||
|
template <handle_results HandleResults, handle_errors HandleErrors,
|
||||||
|
typename Continuation, typename Callback, typename Executor>
|
||||||
|
auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||||
|
Executor&& executor) {
|
||||||
|
static_assert(is_continuable<std::decay_t<Continuation>>{},
|
||||||
|
"Expected a continuation!");
|
||||||
|
|
||||||
|
using Hint = decltype(hints::hint_of(traits::identify<Continuation>()));
|
||||||
|
constexpr auto next_hint =
|
||||||
|
next_hint_of(std::integral_constant<handle_results, HandleResults>{},
|
||||||
|
traits::identify<decltype(callback)>{}, Hint{});
|
||||||
|
|
||||||
|
// TODO consume only the data here so the freeze isn't needed
|
||||||
|
auto ownership_ = attorney::ownership_of(continuation);
|
||||||
|
continuation.freeze();
|
||||||
|
|
||||||
|
return attorney::create(
|
||||||
|
[
|
||||||
|
continuation = std::forward<Continuation>(continuation),
|
||||||
|
callback = std::forward<Callback>(callback),
|
||||||
|
executor = std::forward<Executor>(executor)
|
||||||
|
](auto&& next_callback) mutable {
|
||||||
|
|
||||||
|
// Invokes a continuation with a given callback.
|
||||||
|
// Passes the next callback to the resulting continuable or
|
||||||
|
// invokes the next callback directly if possible.
|
||||||
|
//
|
||||||
|
// For example given:
|
||||||
|
// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||||
|
// - Callback: [](std::string) { }
|
||||||
|
// - NextCallback: []() { }
|
||||||
|
auto proxy =
|
||||||
|
callbacks::make_callback<Hint, HandleResults, HandleErrors>(
|
||||||
|
std::move(callback), std::move(executor),
|
||||||
|
std::forward<decltype(next_callback)>(next_callback));
|
||||||
|
|
||||||
|
// Invoke the continuation with a proxy callback.
|
||||||
|
// The proxy callback is responsible for passing
|
||||||
|
// the result to the callback as well as decorating it.
|
||||||
|
attorney::invoke_continuation(std::move(continuation),
|
||||||
|
std::move(proxy));
|
||||||
|
},
|
||||||
|
next_hint, ownership_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Final invokes the given continuation chain:
|
||||||
|
///
|
||||||
|
/// For example given:
|
||||||
|
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||||
|
template <typename Continuation>
|
||||||
|
void finalize_continuation(Continuation&& continuation) {
|
||||||
|
attorney::invoke_continuation(std::forward<Continuation>(continuation),
|
||||||
|
callbacks::final_callback{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Workaround for GCC bug:
|
||||||
|
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
||||||
|
template <typename T>
|
||||||
|
class supplier_callback {
|
||||||
|
T data_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit supplier_callback(T data) : data_(std::move(data)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
auto operator()(Args...) {
|
||||||
|
return std::move(data_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Returns a continuable into a callable object returning the continuable
|
||||||
|
template <typename Continuation>
|
||||||
|
auto wrap_continuation(Continuation&& continuation) {
|
||||||
|
continuation.freeze();
|
||||||
|
return supplier_callback<std::decay_t<Continuation>>(
|
||||||
|
std::forward<Continuation>(continuation));
|
||||||
|
}
|
||||||
|
} // namespace base
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_BASE_HPP_INCLUDED
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -35,10 +35,11 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/continuable-traverse.hpp>
|
#include <continuable/continuable-traverse.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/flat-variant.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -54,69 +55,62 @@ namespace connection {
|
|||||||
/// - single async value -> single value
|
/// - single async value -> single value
|
||||||
/// - multiple async value -> tuple of async values.
|
/// - multiple async value -> tuple of async values.
|
||||||
namespace aggregated {
|
namespace aggregated {
|
||||||
|
|
||||||
/// Guards a type to be default constructible,
|
/// Guards a type to be default constructible,
|
||||||
/// and wraps it into an optional type if it isn't default constructible.
|
/// and wraps it into an optional type if it isn't default constructible.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using lazy_value_t = std::conditional_t<std::is_default_constructible<T>::value,
|
using lazy_value_t = std::conditional_t<std::is_default_constructible<T>::value,
|
||||||
T, result<T>>;
|
T, container::flat_variant<T>>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
decltype(auto) unpack_lazy(std::true_type /*is_default_constructible*/,
|
decltype(auto) unpack_lazy(T&& value) {
|
||||||
T&& value) {
|
|
||||||
return std::forward<T>(value);
|
return std::forward<T>(value);
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T&& unpack_lazy(std::false_type /*is_default_constructible*/,
|
T&& unpack_lazy(container::flat_variant<T>&& value) {
|
||||||
result<T>&& value) {
|
assert(value.template is<T>() &&
|
||||||
assert(value.is_value() &&
|
|
||||||
"The connection was finalized before all values were present!");
|
"The connection was finalized before all values were present!");
|
||||||
|
|
||||||
return std::move(value).get_value();
|
return std::move(value.template cast<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
class continuable_box;
|
class continuable_box;
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
class continuable_box<continuable_base<Data, identity<>>> {
|
class continuable_box<continuable_base<Data, hints::signature_hint_tag<>>> {
|
||||||
|
|
||||||
continuable_base<Data, identity<>> continuable_;
|
continuable_base<Data, hints::signature_hint_tag<>> continuable_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(continuable_base<Data, identity<>>&& continuable)
|
explicit continuable_box(
|
||||||
: continuable_(std::move(continuable)) {}
|
continuable_base<Data, hints::signature_hint_tag<>>&& continuable)
|
||||||
|
: continuable_(std::move(continuable)) {
|
||||||
auto const& peek() const {
|
|
||||||
return continuable_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto&& fetch() {
|
continuable_base<Data, hints::signature_hint_tag<>>&& fetch() {
|
||||||
return std::move(continuable_);
|
return std::move(continuable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign() {}
|
void assign() {
|
||||||
|
}
|
||||||
|
|
||||||
auto unbox() && {
|
auto unbox() && {
|
||||||
return spread_this();
|
return spread_this();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Data, typename First>
|
template <typename Data, typename First>
|
||||||
class continuable_box<continuable_base<Data, identity<First>>> {
|
class continuable_box<
|
||||||
|
continuable_base<Data, hints::signature_hint_tag<First>>> {
|
||||||
|
|
||||||
continuable_base<Data, identity<First>> continuable_;
|
continuable_base<Data, hints::signature_hint_tag<First>> continuable_;
|
||||||
lazy_value_t<First> first_;
|
lazy_value_t<First> first_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(
|
explicit continuable_box(
|
||||||
continuable_base<Data, identity<First>>&& continuable)
|
continuable_base<Data, hints::signature_hint_tag<First>>&& continuable)
|
||||||
: continuable_(std::move(continuable)) {}
|
: continuable_(std::move(continuable)) {
|
||||||
|
|
||||||
auto const& peek() const {
|
|
||||||
return continuable_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto&& fetch() {
|
continuable_base<Data, hints::signature_hint_tag<First>>&& fetch() {
|
||||||
return std::move(continuable_);
|
return std::move(continuable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,27 +119,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto unbox() && {
|
auto unbox() && {
|
||||||
return unpack_lazy(std::is_default_constructible<First>{},
|
return unpack_lazy(std::move(first_));
|
||||||
std::move(first_));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename Data, typename First, typename Second, typename... Rest>
|
template <typename Data, typename First, typename Second, typename... Rest>
|
||||||
class continuable_box<
|
class continuable_box<
|
||||||
continuable_base<Data, identity<First, Second, Rest...>>> {
|
continuable_base<Data, hints::signature_hint_tag<First, Second, Rest...>>> {
|
||||||
|
|
||||||
continuable_base<Data, identity<First, Second, Rest...>> continuable_;
|
continuable_base<Data, hints::signature_hint_tag<First, Second, Rest...>>
|
||||||
|
continuable_;
|
||||||
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit continuable_box(
|
explicit continuable_box(
|
||||||
continuable_base<Data, identity<First, Second, Rest...>>&& continuable)
|
continuable_base<Data,
|
||||||
: continuable_(std::move(continuable)) {}
|
hints::signature_hint_tag<First, Second, Rest...>>&&
|
||||||
|
continuable)
|
||||||
auto const& peek() const {
|
: continuable_(std::move(continuable)) {
|
||||||
return continuable_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto&& fetch() {
|
continuable_base<Data, hints::signature_hint_tag<First, Second, Rest...>>&&
|
||||||
|
fetch() {
|
||||||
return std::move(continuable_);
|
return std::move(continuable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,13 +149,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto unbox() && {
|
auto unbox() && {
|
||||||
return traits::unpack(
|
return traits::unpack(unpack_lazy(std::move(args_)), [](auto&&... args) {
|
||||||
[](auto&&... args) {
|
return spread_this(std::forward<decltype(args)>(args)...);
|
||||||
return spread_this(std::forward<decltype(args)>(args)...);
|
});
|
||||||
},
|
|
||||||
unpack_lazy(
|
|
||||||
std::is_default_constructible<std::tuple<First, Second, Rest...>>{},
|
|
||||||
std::move(args_)));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -210,20 +200,21 @@ constexpr auto unbox_continuables(Args&&... args) {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename Callback, typename Data>
|
template <typename Callback, typename Data>
|
||||||
constexpr auto finalize_impl(identity<void>, Callback&& callback, Data&&) {
|
constexpr auto finalize_impl(traits::identity<void>, Callback&& callback,
|
||||||
|
Data&&) {
|
||||||
return std::forward<Callback>(callback)();
|
return std::forward<Callback>(callback)();
|
||||||
}
|
}
|
||||||
template <typename... Args, typename Callback, typename Data>
|
template <typename... Args, typename Callback, typename Data>
|
||||||
constexpr auto finalize_impl(identity<std::tuple<Args...>>, Callback&& callback,
|
constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||||
Data&& data) {
|
Callback&& callback, Data&& data) {
|
||||||
// Call the final callback with the cleaned result
|
// Call the final callback with the cleaned result
|
||||||
return traits::unpack(std::forward<Callback>(callback),
|
return traits::unpack(unbox_continuables(std::forward<Data>(data)),
|
||||||
unbox_continuables(std::forward<Data>(data)));
|
std::forward<Callback>(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hint_mapper {
|
struct hint_mapper {
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr auto operator()(T...) -> identity<T...> {
|
constexpr auto operator()(T...) -> hints::signature_hint_tag<T...> {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -233,7 +224,7 @@ template <typename Callback, typename Data>
|
|||||||
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
||||||
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
||||||
// Guard the final result against void
|
// Guard the final result against void
|
||||||
return detail::finalize_impl(identity<std::decay_t<result_t>>{},
|
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
||||||
std::forward<Callback>(callback),
|
std::forward<Callback>(callback),
|
||||||
std::forward<Data>(data));
|
std::forward<Data>(data));
|
||||||
}
|
}
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -37,13 +37,13 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/connection/connection-aggregated.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/connection/connection.hpp>
|
#include <continuable/detail/connection-aggregated.hpp>
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
#include <continuable/detail/connection.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
#include <continuable/detail/hints.hpp>
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -99,11 +99,11 @@ class result_submitter
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... PartialArgs>
|
template <typename... PartialArgs>
|
||||||
void operator()(exception_arg_t tag, exception_t exception) && {
|
void operator()(types::dispatch_error_tag tag, types::error_type error) && {
|
||||||
// We never complete the connection, but we forward the first error
|
// We never complete the connection, but we forward the first error
|
||||||
// which was raised.
|
// which was raised.
|
||||||
std::call_once(me->flag_, std::move(me->callback_), tag,
|
std::call_once(me->flag_, std::move(me->callback_), tag,
|
||||||
std::move(exception));
|
std::move(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -157,21 +157,22 @@ struct connection_finalizer<connection_strategy_all_tag> {
|
|||||||
template <typename Connection>
|
template <typename Connection>
|
||||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||||
// Create the target result from the connection
|
// Create the target result from the connection
|
||||||
auto res =
|
auto result =
|
||||||
aggregated::box_continuables(std::forward<Connection>(connection));
|
aggregated::box_continuables(std::forward<Connection>(connection));
|
||||||
|
|
||||||
auto signature = aggregated::hint_of_data<decltype(res)>();
|
auto signature = aggregated::hint_of_data<decltype(result)>();
|
||||||
|
|
||||||
|
return base::attorney::create(
|
||||||
|
[result = std::move(result)](auto&& callback) mutable {
|
||||||
|
|
||||||
return base::attorney::create_from(
|
|
||||||
[res = std::move(res)](auto&& callback) mutable {
|
|
||||||
using submitter_t =
|
using submitter_t =
|
||||||
all::result_submitter<std::decay_t<decltype(callback)>,
|
all::result_submitter<std::decay_t<decltype(callback)>,
|
||||||
std::decay_t<decltype(res)>>;
|
std::decay_t<decltype(result)>>;
|
||||||
|
|
||||||
// Create the shared state which holds the result
|
// Create the shared state which holds the result and the final
|
||||||
// and the final callback
|
// callback
|
||||||
auto state = std::make_shared<submitter_t>(
|
auto state = std::make_shared<submitter_t>(
|
||||||
std::forward<decltype(callback)>(callback), std::move(res));
|
std::forward<decltype(callback)>(callback), std::move(result));
|
||||||
|
|
||||||
// Dispatch the continuables and store its partial result
|
// Dispatch the continuables and store its partial result
|
||||||
// in the whole result
|
// in the whole result
|
||||||
@ -185,13 +186,6 @@ struct connection_finalizer<connection_strategy_all_tag> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace connection
|
} // namespace connection
|
||||||
|
|
||||||
/// Specialization for a connection annotation
|
|
||||||
template <>
|
|
||||||
struct annotation_trait<connection::connection_strategy_all_tag>
|
|
||||||
: connection::connection_annotation_trait<
|
|
||||||
connection::connection_strategy_all_tag> {};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -37,14 +37,14 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-promise-base.hpp>
|
#include <continuable/continuable-promise-base.hpp>
|
||||||
#include <continuable/continuable-traverse.hpp>
|
#include <continuable/continuable-traverse.hpp>
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
#include <continuable/detail/container-category.hpp>
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/hints.hpp>
|
||||||
#include <continuable/detail/traversal/container-category.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -88,30 +88,30 @@ private:
|
|||||||
|
|
||||||
struct result_deducer {
|
struct result_deducer {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce_one(std::false_type, identity<T>) {
|
static auto deduce_one(std::false_type, traits::identity<T>) {
|
||||||
static_assert(traits::fail<T>::value,
|
static_assert(traits::fail<T>::value,
|
||||||
"Non continuable types except tuple like and homogeneous "
|
"Non continuable types except tuple like and homogeneous "
|
||||||
"containers aren't allowed inside an any expression!");
|
"containers aren't allowed inside an any expression!");
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce_one(std::true_type, identity<T> id) {
|
static auto deduce_one(std::true_type, traits::identity<T> id) {
|
||||||
return base::annotation_of(id);
|
return hints::hint_of(id);
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce(traversal::container_category_tag<false, false>,
|
static auto deduce(traversal::container_category_tag<false, false>,
|
||||||
identity<T> id) {
|
traits::identity<T> id) {
|
||||||
return deduce_one<T>(base::is_continuable<T>{}, id);
|
return deduce_one<T>(base::is_continuable<T>{}, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce a homogeneous container
|
/// Deduce a homogeneous container
|
||||||
template <bool IsTupleLike, typename T>
|
template <bool IsTupleLike, typename T>
|
||||||
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
||||||
identity<T>) {
|
traits::identity<T>) {
|
||||||
|
|
||||||
// Deduce the containing type
|
// Deduce the containing type
|
||||||
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
||||||
return deduce(traversal::container_category_of_t<element_t>{},
|
return deduce(traversal::container_category_of_t<element_t>{},
|
||||||
identity<element_t>{});
|
traits::identity<element_t>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename First, typename... T>
|
template <typename First, typename... T>
|
||||||
@ -125,18 +125,19 @@ struct result_deducer {
|
|||||||
|
|
||||||
template <std::size_t... I, typename T>
|
template <std::size_t... I, typename T>
|
||||||
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
||||||
identity<T>) {
|
traits::identity<T>) {
|
||||||
|
|
||||||
return deduce_same_hints(deduce(
|
return deduce_same_hints(deduce(
|
||||||
traversal::container_category_of_t<
|
traversal::container_category_of_t<
|
||||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
||||||
identity<std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
traits::identity<
|
||||||
|
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverse tuple like container
|
/// Traverse tuple like container
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto deduce(traversal::container_category_tag<false, true>,
|
static auto deduce(traversal::container_category_tag<false, true>,
|
||||||
identity<T> id) {
|
traits::identity<T> id) {
|
||||||
|
|
||||||
constexpr auto const size = std::tuple_size<T>::value;
|
constexpr auto const size = std::tuple_size<T>::value;
|
||||||
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
||||||
@ -171,11 +172,12 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
|||||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||||
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
||||||
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
||||||
identity<std::decay_t<Connection>>{})){};
|
traits::identity<std::decay_t<Connection>>{})){};
|
||||||
|
|
||||||
return base::attorney::create_from(
|
return base::attorney::create(
|
||||||
[connection =
|
[connection =
|
||||||
std::forward<Connection>(connection)](auto&& callback) mutable {
|
std::forward<Connection>(connection)](auto&& callback) mutable {
|
||||||
|
|
||||||
using submitter_t =
|
using submitter_t =
|
||||||
any::any_result_submitter<std::decay_t<decltype(callback)>>;
|
any::any_result_submitter<std::decay_t<decltype(callback)>>;
|
||||||
|
|
||||||
@ -191,13 +193,6 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace connection
|
} // namespace connection
|
||||||
|
|
||||||
/// Specialization for a connection annotation
|
|
||||||
template <>
|
|
||||||
struct annotation_trait<connection::connection_strategy_any_tag>
|
|
||||||
: connection::connection_annotation_trait<
|
|
||||||
connection::connection_strategy_any_tag> {};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -36,12 +36,12 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-traverse-async.hpp>
|
#include <continuable/continuable-traverse-async.hpp>
|
||||||
#include <continuable/detail/connection/connection-aggregated.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
#include <continuable/detail/connection-aggregated.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -56,16 +56,16 @@ auto sequential_connect(Left&& left, Right&& right) {
|
|||||||
left.freeze(right.is_frozen());
|
left.freeze(right.is_frozen());
|
||||||
right.freeze();
|
right.freeze();
|
||||||
|
|
||||||
return std::forward<Left>(left).then(
|
return std::forward<Left>(left).then([right = std::forward<Right>(right)](
|
||||||
[right = std::forward<Right>(right)](auto&&... args) mutable {
|
auto&&... args) mutable {
|
||||||
return std::move(right).then(
|
return std::move(right).then([previous = std::make_tuple(
|
||||||
[previous = std::make_tuple(std::forward<decltype(args)>(args)...)](
|
std::forward<decltype(args)>(args)...)](
|
||||||
auto&&... args) mutable {
|
auto&&... args) mutable {
|
||||||
return std::tuple_cat(
|
return traits::merge(
|
||||||
std::move(previous),
|
std::move(previous),
|
||||||
std::make_tuple(std::forward<decltype(args)>(args)...));
|
std::make_tuple(std::forward<decltype(args)>(args)...));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callback, typename Box>
|
template <typename Callback, typename Box>
|
||||||
@ -94,34 +94,25 @@ public:
|
|||||||
|
|
||||||
template <typename Box, std::enable_if_t<aggregated::is_continuable_box<
|
template <typename Box, std::enable_if_t<aggregated::is_continuable_box<
|
||||||
std::decay_t<Box>>::value>* = nullptr>
|
std::decay_t<Box>>::value>* = nullptr>
|
||||||
bool operator()(async_traverse_visit_tag, Box&& box) {
|
bool operator()(async_traverse_visit_tag, Box&& /*box*/) {
|
||||||
if (base::attorney::is_ready(box.peek())) {
|
return false;
|
||||||
// The result can be resolved directly
|
|
||||||
traits::unpack(
|
|
||||||
[&](auto&&... args) mutable {
|
|
||||||
box.assign(std::forward<decltype(args)>(args)...);
|
|
||||||
},
|
|
||||||
base::attorney::query(box.fetch()));
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Box, typename N>
|
template <typename Box, typename N>
|
||||||
void operator()(async_traverse_detach_tag, Box&& box, N&& next) {
|
void operator()(async_traverse_detach_tag, Box&& box, N&& next) {
|
||||||
box.fetch()
|
box.fetch()
|
||||||
.then([box = std::addressof(box),
|
.then([ box = std::addressof(box),
|
||||||
next = std::forward<N>(next)](auto&&... args) mutable {
|
next = std::forward<N>(next) ](auto&&... args) mutable {
|
||||||
|
|
||||||
// Assign the result to the target
|
// Assign the result to the target
|
||||||
box->assign(std::forward<decltype(args)>(args)...);
|
box->assign(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
// Continue the asynchronous sequential traversal
|
// Continue the asynchronous sequential traversal
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
.fail([me = this->shared_from_this()](exception_t exception) {
|
.fail([me = this->shared_from_this()](types::error_type exception) {
|
||||||
// Abort the traversal when an error occurred
|
// Abort the traversal when an error occurred
|
||||||
std::move(me->data_.callback)(exception_arg_t{},
|
std::move(me->data_.callback)(types::dispatch_error_tag{},
|
||||||
std::move(exception));
|
std::move(exception));
|
||||||
})
|
})
|
||||||
.done();
|
.done();
|
||||||
@ -147,36 +138,30 @@ struct connection_finalizer<connection_strategy_seq_tag> {
|
|||||||
template <typename Connection>
|
template <typename Connection>
|
||||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||||
|
|
||||||
auto res =
|
auto result =
|
||||||
aggregated::box_continuables(std::forward<Connection>(connection));
|
aggregated::box_continuables(std::forward<Connection>(connection));
|
||||||
|
|
||||||
auto signature = aggregated::hint_of_data<decltype(res)>();
|
auto signature = aggregated::hint_of_data<decltype(result)>();
|
||||||
|
|
||||||
|
return base::attorney::create(
|
||||||
|
[result = std::move(result)](auto&& callback) mutable {
|
||||||
|
|
||||||
return base::attorney::create_from(
|
|
||||||
[res = std::move(res)](auto&& callback) mutable {
|
|
||||||
// The data from which the visitor is constructed in-place
|
// The data from which the visitor is constructed in-place
|
||||||
using data_t =
|
using data_t =
|
||||||
seq::sequential_dispatch_data<std::decay_t<decltype(callback)>,
|
seq::sequential_dispatch_data<std::decay_t<decltype(callback)>,
|
||||||
std::decay_t<decltype(res)>>;
|
std::decay_t<decltype(result)>>;
|
||||||
|
|
||||||
// The visitor type
|
// The visitor type
|
||||||
using visitor_t = seq::sequential_dispatch_visitor<data_t>;
|
using visitor_t = seq::sequential_dispatch_visitor<data_t>;
|
||||||
|
|
||||||
traverse_pack_async(async_traverse_in_place_tag<visitor_t>{},
|
traverse_pack_async(async_traverse_in_place_tag<visitor_t>{},
|
||||||
data_t{std::forward<decltype(callback)>(callback),
|
data_t{std::forward<decltype(callback)>(callback),
|
||||||
std::move(res)});
|
std::move(result)});
|
||||||
},
|
},
|
||||||
signature, std::move(ownership));
|
signature, std::move(ownership));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace connection
|
} // namespace connection
|
||||||
|
|
||||||
/// Specialization for a connection annotation
|
|
||||||
template <>
|
|
||||||
struct annotation_trait<connection::connection_strategy_seq_tag>
|
|
||||||
: connection::connection_annotation_trait<
|
|
||||||
connection::connection_strategy_seq_tag> {};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -35,11 +35,12 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <continuable/continuable-traverse.hpp>
|
#include <continuable/continuable-traverse.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/core/types.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -55,7 +56,7 @@ template <typename... LeftArgs, typename... RightArgs>
|
|||||||
auto chain_connection(std::tuple<LeftArgs...> leftPack,
|
auto chain_connection(std::tuple<LeftArgs...> leftPack,
|
||||||
std::tuple<RightArgs...> rightPack) {
|
std::tuple<RightArgs...> rightPack) {
|
||||||
|
|
||||||
return std::tuple_cat(std::move(leftPack), std::move(rightPack));
|
return traits::merge(std::move(leftPack), std::move(rightPack));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes a continuation to a tuple holding an arbitrary count of
|
/// Normalizes a continuation to a tuple holding an arbitrary count of
|
||||||
@ -83,7 +84,7 @@ auto normalize(Strategy /*strategy*/,
|
|||||||
|
|
||||||
// If the right continuation is a different strategy materialize it
|
// If the right continuation is a different strategy materialize it
|
||||||
// in order to keep the precedence in cases where: `c1 && (c2 || c3)`.
|
// in order to keep the precedence in cases where: `c1 && (c2 || c3)`.
|
||||||
return std::make_tuple(std::move(continuation).finish());
|
return std::make_tuple(base::attorney::materialize(std::move(continuation)));
|
||||||
}
|
}
|
||||||
/// - The continuable is inside the current strategy state:
|
/// - The continuable is inside the current strategy state:
|
||||||
/// -> return the data of the tuple
|
/// -> return the data of the tuple
|
||||||
@ -92,7 +93,7 @@ auto normalize(Strategy /*strategy*/,
|
|||||||
continuable_base<Data, Strategy>&& continuation) {
|
continuable_base<Data, Strategy>&& continuation) {
|
||||||
|
|
||||||
// If we are in the given strategy we can just use the data of the continuable
|
// If we are in the given strategy we can just use the data of the continuable
|
||||||
return base::attorney::consume(std::move(continuation));
|
return base::attorney::consume_data(std::move(continuation));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry function for connecting two continuables with a given strategy.
|
/// Entry function for connecting two continuables with a given strategy.
|
||||||
@ -114,7 +115,7 @@ auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
|
|||||||
|
|
||||||
// Return a new continuable containing the tuple and holding
|
// Return a new continuable containing the tuple and holding
|
||||||
// the current strategy as annotation.
|
// the current strategy as annotation.
|
||||||
return base::attorney::create_from_raw(std::move(data), strategy, ownership_);
|
return base::attorney::create(std::move(data), strategy, ownership_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All strategies should specialize this class in order to provide:
|
/// All strategies should specialize this class in order to provide:
|
||||||
@ -124,24 +125,32 @@ auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
|
|||||||
template <typename Strategy>
|
template <typename Strategy>
|
||||||
struct connection_finalizer;
|
struct connection_finalizer;
|
||||||
|
|
||||||
template <typename Strategy>
|
/// Finalizes the connection logic of a given connection
|
||||||
struct connection_annotation_trait {
|
template <typename Data, typename Strategy>
|
||||||
/// Finalizes the connection logic of a given connection
|
auto finalize_connection(continuable_base<Data, Strategy>&& continuation) {
|
||||||
template <typename Continuable>
|
using finalizer = connection_finalizer<Strategy>;
|
||||||
static auto finish(Continuable&& continuable) {
|
|
||||||
using finalizer = connection_finalizer<Strategy>;
|
|
||||||
|
|
||||||
util::ownership ownership = base::attorney::ownership_of(continuable);
|
util::ownership ownership = base::attorney::ownership_of(continuation);
|
||||||
auto connection =
|
auto connection = base::attorney::consume_data(std::move(continuation));
|
||||||
base::attorney::consume(std::forward<Continuable>(continuable));
|
|
||||||
|
|
||||||
// Return a new continuable which
|
// Return a new continuable which
|
||||||
return finalizer::finalize(std::move(connection), std::move(ownership));
|
return finalizer::finalize(std::move(connection), std::move(ownership));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A base class from which the continuable may inherit in order to
|
||||||
|
/// provide a materializer method which will finalize an oustanding strategy.
|
||||||
|
template <typename Continuable, typename = void>
|
||||||
|
struct materializer {
|
||||||
|
static constexpr auto&& apply(Continuable&& continuable) {
|
||||||
|
return std::move(continuable);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
template <typename Data, typename Strategy>
|
||||||
|
struct materializer<continuable_base<Data, Strategy>,
|
||||||
|
std::enable_if_t<is_connection_strategy<Strategy>::value>> {
|
||||||
|
|
||||||
template <typename Continuable>
|
static constexpr auto apply(continuable_base<Data, Strategy>&& continuable) {
|
||||||
static bool is_ready(Continuable const& /*continuable*/) noexcept {
|
return finalize_connection(std::move(continuable));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,7 +180,7 @@ public:
|
|||||||
|
|
||||||
// Materialize every continuable
|
// Materialize every continuable
|
||||||
// TODO Actually we would just need to consume the data here
|
// TODO Actually we would just need to consume the data here
|
||||||
return std::forward<Continuable>(continuable).finish();
|
return base::attorney::materialize(std::forward<Continuable>(continuable));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -33,7 +33,8 @@
|
|||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
File diff suppressed because it is too large
Load Diff
164
include/continuable/detail/expected.hpp
Normal file
164
include/continuable/detail/expected.hpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <continuable/detail/flat-variant.hpp>
|
||||||
|
#include <continuable/detail/hints.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace container {
|
||||||
|
/// A class similar to the one in the expected proposal,
|
||||||
|
/// however it is capable of carrying an exception_ptr if
|
||||||
|
/// exceptions are used.
|
||||||
|
template <typename T>
|
||||||
|
class expected {
|
||||||
|
flat_variant<T, types::error_type> variant_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit expected() = default;
|
||||||
|
explicit expected(expected const&) = default;
|
||||||
|
explicit expected(expected&&) = default;
|
||||||
|
expected& operator=(expected const&) = default;
|
||||||
|
expected& operator=(expected&&) = default;
|
||||||
|
~expected() = default;
|
||||||
|
|
||||||
|
explicit expected(T value) : variant_(std::move(value)) {
|
||||||
|
}
|
||||||
|
explicit expected(types::error_type exception)
|
||||||
|
: variant_(std::move(exception)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
expected& operator=(T value) {
|
||||||
|
variant_ = std::move(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
expected& operator=(types::error_type exception) {
|
||||||
|
variant_ = std::move(exception);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_value(T value) {
|
||||||
|
variant_ = std::move(value);
|
||||||
|
}
|
||||||
|
void set_exception(types::error_type exception) {
|
||||||
|
variant_ = std::move(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_value() const noexcept {
|
||||||
|
return variant_.template is<T>();
|
||||||
|
}
|
||||||
|
bool is_exception() const noexcept {
|
||||||
|
return variant_.template is<types::error_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit constexpr operator bool() const noexcept {
|
||||||
|
return is_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& get_value() noexcept {
|
||||||
|
return variant_.template cast<T>();
|
||||||
|
}
|
||||||
|
T const& get_value() const noexcept {
|
||||||
|
return variant_.template cast<T>();
|
||||||
|
}
|
||||||
|
types::error_type& get_exception() noexcept {
|
||||||
|
return variant_.template cast<types::error_type>();
|
||||||
|
}
|
||||||
|
types::error_type const& get_exception() const noexcept {
|
||||||
|
return variant_.template cast<types::error_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*() noexcept {
|
||||||
|
return get_value();
|
||||||
|
}
|
||||||
|
T const& operator*() const noexcept {
|
||||||
|
return get_value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
struct void_guard_tag {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct expected_result_trait;
|
||||||
|
template <>
|
||||||
|
struct expected_result_trait<traits::identity<>> {
|
||||||
|
using expected_type = expected<void_guard_tag>;
|
||||||
|
|
||||||
|
static constexpr void_guard_tag wrap() noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
static void unwrap(expected_type&& e) {
|
||||||
|
assert(e.is_value());
|
||||||
|
(void)e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct expected_result_trait<traits::identity<T>> {
|
||||||
|
using expected_type = expected<T>;
|
||||||
|
|
||||||
|
static auto wrap(T arg) {
|
||||||
|
return std::move(arg);
|
||||||
|
}
|
||||||
|
static auto unwrap(expected_type&& e) {
|
||||||
|
assert(e.is_value());
|
||||||
|
return std::move(e.get_value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename First, typename Second, typename... Rest>
|
||||||
|
struct expected_result_trait<traits::identity<First, Second, Rest...>> {
|
||||||
|
using expected_type = expected<std::tuple<First, Second, Rest...>>;
|
||||||
|
|
||||||
|
static auto wrap(First first, Second second, Rest... rest) {
|
||||||
|
return std::make_tuple(std::move(first), std::move(second),
|
||||||
|
std::move(rest)...);
|
||||||
|
}
|
||||||
|
static auto unwrap(expected_type&& e) {
|
||||||
|
assert(e.is_value());
|
||||||
|
return std::move(e.get_value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename Continuable>
|
||||||
|
using expected_result_trait_t = detail::expected_result_trait<decltype(
|
||||||
|
hints::hint_of(traits::identify<Continuable>{}))>;
|
||||||
|
} // namespace container
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED
|
||||||
242
include/continuable/detail/external/asio.hpp
vendored
242
include/continuable/detail/external/asio.hpp
vendored
@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
|
|
||||||
#if defined(ASIO_STANDALONE)
|
|
||||||
# include <asio/async_result.hpp>
|
|
||||||
# include <asio/error.hpp>
|
|
||||||
# include <asio/error_code.hpp>
|
|
||||||
# include <asio/version.hpp>
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <asio/system_error.hpp>
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if (ASIO_VERSION < 101300) // 1.13.0
|
|
||||||
# define CTI_DETAIL_ASIO_HAS_NO_INTEGRATION
|
|
||||||
# elif (ASIO_VERSION < 101600) // 1.16.0 (boost 1.72 baseline)
|
|
||||||
# define CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define CTI_DETAIL_ASIO_NAMESPACE_BEGIN namespace asio {
|
|
||||||
# define CTI_DETAIL_ASIO_NAMESPACE_END }
|
|
||||||
#else
|
|
||||||
# include <boost/asio/async_result.hpp>
|
|
||||||
# include <boost/asio/error.hpp>
|
|
||||||
# include <boost/system/error_code.hpp>
|
|
||||||
# include <boost/version.hpp>
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <boost/system/system_error.hpp>
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if (BOOST_VERSION < 107000) // 1.70
|
|
||||||
# define CTI_DETAIL_ASIO_HAS_NO_INTEGRATION
|
|
||||||
# elif (BOOST_VERSION < 107200) // 1.72
|
|
||||||
# define CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define CTI_DETAIL_ASIO_NAMESPACE_BEGIN \
|
|
||||||
namespace boost { \
|
|
||||||
namespace asio {
|
|
||||||
# define CTI_DETAIL_ASIO_NAMESPACE_END \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CTI_DETAIL_ASIO_HAS_NO_INTEGRATION)
|
|
||||||
# error "First-class ASIO support for continuable requires the form of "\
|
|
||||||
"`async_result` with an `initiate` static member function, which was added " \
|
|
||||||
"in standalone ASIO 1.13.0 and Boost ASIO 1.70. Older versions can be " \
|
|
||||||
"integrated manually with `cti::promisify`."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace asio {
|
|
||||||
|
|
||||||
#if defined(ASIO_STANDALONE)
|
|
||||||
using error_code_t = ::asio::error_code;
|
|
||||||
using basic_errors_t = ::asio::error::basic_errors;
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
using system_error_t = ::asio::system_error;
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
using error_code_t = ::boost::system::error_code;
|
|
||||||
using basic_errors_t = ::boost::asio::error::basic_errors;
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
using system_error_t = ::boost::system::system_error;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Promise, typename Token>
|
|
||||||
class promise_resolver {
|
|
||||||
public:
|
|
||||||
explicit promise_resolver(Promise promise, Token token)
|
|
||||||
: promise_(std::move(promise))
|
|
||||||
, token_(std::move(token)) {}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
void operator()(T&&... args) noexcept {
|
|
||||||
promise_.set_value(std::forward<T>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
void operator()(error_code_t e, T&&... args) noexcept {
|
|
||||||
if (e) {
|
|
||||||
if (!token_.is_ignored(e)) {
|
|
||||||
if (token_.is_cancellation(e)) {
|
|
||||||
promise_.set_canceled();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
promise_.set_exception(
|
|
||||||
std::make_exception_ptr(system_error_t(std::move(e))));
|
|
||||||
#else
|
|
||||||
promise_.set_exception(exception_t(e.value(), e.category()));
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
promise_.set_value(std::forward<T>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Promise promise_;
|
|
||||||
Token token_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Binds `promise` to the first argument of a continuable resolver, giving it
|
|
||||||
// the signature of an ASIO handler.
|
|
||||||
template <typename Promise, typename Token>
|
|
||||||
auto promise_resolver_handler(Promise&& promise, Token&& token) noexcept {
|
|
||||||
return promise_resolver<std::decay_t<Promise>, std::decay_t<Token>>(
|
|
||||||
std::forward<Promise>(promise), std::forward<Token>(token));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper struct wrapping a call to `cti::make_continuable` and, if needed,
|
|
||||||
// providing an erased, explicit `return_type` for `async_result`.
|
|
||||||
template <typename Signature>
|
|
||||||
struct initiate_make_continuable;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
struct initiate_make_continuable<void(Args...)> {
|
|
||||||
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
|
|
||||||
using erased_return_type = continuable<Args...>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Continuation>
|
|
||||||
auto operator()(Continuation&& continuation) {
|
|
||||||
return base::attorney::create_from(std::forward<Continuation>(continuation),
|
|
||||||
identity<Args...>{}, util::ownership{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
struct initiate_make_continuable<void(error_code_t, Args...)> {
|
|
||||||
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
|
|
||||||
using erased_return_type = continuable<Args...>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Continuation>
|
|
||||||
auto operator()(Continuation&& continuation) {
|
|
||||||
return base::attorney::create_from(std::forward<Continuation>(continuation),
|
|
||||||
identity<Args...>{}, util::ownership{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
struct initiate_make_continuable<void(error_code_t const&, Args...)>
|
|
||||||
: initiate_make_continuable<void(error_code_t, Args...)> {};
|
|
||||||
|
|
||||||
struct map_default {
|
|
||||||
constexpr map_default() noexcept {}
|
|
||||||
|
|
||||||
bool is_cancellation(error_code_t const& ec) const noexcept {
|
|
||||||
// Continuable uses a default constructed exception type to signal
|
|
||||||
// cancellation to the followed asynchronous control flow.
|
|
||||||
return ec == basic_errors_t::operation_aborted;
|
|
||||||
}
|
|
||||||
bool is_ignored(error_code_t const& /*ec*/) const noexcept {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct map_none {
|
|
||||||
constexpr map_none() noexcept {}
|
|
||||||
|
|
||||||
bool is_cancellation(error_code_t const& /*ec*/) const noexcept {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool is_ignored(error_code_t const& /*ec*/) const noexcept {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t Size>
|
|
||||||
class map_ignore {
|
|
||||||
public:
|
|
||||||
map_ignore(std::array<basic_errors_t, Size> ignored) noexcept
|
|
||||||
: ignored_(ignored) {}
|
|
||||||
|
|
||||||
bool is_cancellation(error_code_t const& ec) const noexcept {
|
|
||||||
return ec == basic_errors_t::operation_aborted;
|
|
||||||
}
|
|
||||||
bool is_ignored(error_code_t const& ec) const noexcept {
|
|
||||||
for (basic_errors_t ignored : ignored_) {
|
|
||||||
if (ec == ignored) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::array<basic_errors_t, Size> ignored_;
|
|
||||||
};
|
|
||||||
} // namespace asio
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -33,19 +33,19 @@
|
|||||||
|
|
||||||
// Defines CONTINUABLE_WITH_NO_EXCEPTIONS when exception support is disabled
|
// Defines CONTINUABLE_WITH_NO_EXCEPTIONS when exception support is disabled
|
||||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
# if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# if !defined(_HAS_EXCEPTIONS) || (_HAS_EXCEPTIONS == 0)
|
#if !defined(_HAS_EXCEPTIONS) || (_HAS_EXCEPTIONS == 0)
|
||||||
# define CONTINUABLE_WITH_NO_EXCEPTIONS
|
#define CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
# endif
|
#endif
|
||||||
# elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
# if !(__EXCEPTIONS && __has_feature(cxx_exceptions))
|
#if !(__EXCEPTIONS && __has_feature(cxx_exceptions))
|
||||||
# define CONTINUABLE_WITH_NO_EXCEPTIONS
|
#define CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
# endif
|
#endif
|
||||||
# elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
# if !__EXCEPTIONS
|
#if !__EXCEPTIONS
|
||||||
# define CONTINUABLE_WITH_NO_EXCEPTIONS
|
#define CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
# endif
|
#endif
|
||||||
# endif
|
#endif
|
||||||
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS
|
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@ -55,11 +55,8 @@
|
|||||||
#define CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
|
#define CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
|
||||||
#define CONTINUABLE_HAS_CXX17_DISJUNCTION
|
#define CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||||
#define CONTINUABLE_HAS_CXX17_CONJUNCTION
|
#define CONTINUABLE_HAS_CXX17_CONJUNCTION
|
||||||
#define CONTINUABLE_HAS_CXX17_VOID_T
|
|
||||||
#else
|
#else
|
||||||
// Generic feature detection based on __has_feature
|
// Generic feature detection based on __has_feature
|
||||||
// and other preprocessor definitions based on:
|
|
||||||
// http://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
|
|
||||||
#if defined(__has_feature)
|
#if defined(__has_feature)
|
||||||
#if !defined(CONTINUABLE_HAS_CXX17_CONSTEXPR_IF) && \
|
#if !defined(CONTINUABLE_HAS_CXX17_CONSTEXPR_IF) && \
|
||||||
__has_feature(cxx_if_constexpr)
|
__has_feature(cxx_if_constexpr)
|
||||||
@ -78,49 +75,19 @@
|
|||||||
(__cpp_lib_experimental_logical_traits >= 201511)
|
(__cpp_lib_experimental_logical_traits >= 201511)
|
||||||
#define CONTINUABLE_HAS_CXX17_CONJUNCTION
|
#define CONTINUABLE_HAS_CXX17_CONJUNCTION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CONTINUABLE_HAS_CXX17_VOID_T) && \
|
|
||||||
defined(__cpp_lib_void_t) && \
|
|
||||||
(__cpp_lib_void_t >= 201411)
|
|
||||||
#define CONTINUABLE_HAS_CXX17_VOID_T
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Automatically detects support for coroutines.
|
/// Usually this is enabled by the CMake project
|
||||||
// Parts of this detection mechanism were adapted from boost::asio,
|
#if !defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE) && \
|
||||||
// with support added for experimental coroutines.
|
defined(__cpp_coroutines) && (__cpp_coroutines >= 201707)
|
||||||
#if !defined(CONTINUABLE_HAS_DISABLED_COROUTINE) \
|
#define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
&& !defined(CONTINUABLE_HAS_COROUTINE)
|
#endif
|
||||||
/// Define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE when
|
|
||||||
/// CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE is defined.
|
/// Define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE when
|
||||||
#if defined(CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE)
|
/// CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE is defined.
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
#if !defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE) && \
|
||||||
#elif defined(CONTINUABLE_WITH_COROUTINE)
|
defined(CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE)
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
#define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
#define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE 1
|
|
||||||
#elif defined(_MSC_VER) // Visual Studio
|
|
||||||
#if (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705)
|
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
|
||||||
#elif _MSC_FULL_VER >= 190023506
|
|
||||||
#if defined(_RESUMABLE_FUNCTIONS_SUPPORTED)
|
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
|
||||||
#define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE 1
|
|
||||||
#endif // defined(_RESUMABLE_FUNCTIONS_SUPPORTED)
|
|
||||||
#endif // _MSC_FULL_VER >= 190023506
|
|
||||||
#elif defined(__clang__) // Clang
|
|
||||||
#if defined(__cpp_coroutines) && (__cpp_coroutines >= 201703L)
|
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
|
||||||
#if defined(_LIBCPP_EXPERIMENTAL_COROUTINE)
|
|
||||||
#define CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE 1
|
|
||||||
#endif
|
|
||||||
#endif // defined(__cpp_coroutines) && (__cpp_coroutines >= 201703L)
|
|
||||||
#elif defined(__GNUC__) // GCC
|
|
||||||
#if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)
|
|
||||||
#if __has_include(<coroutine>)
|
|
||||||
#define CONTINUABLE_HAS_COROUTINE 1
|
|
||||||
#endif // __has_include(<coroutine>)
|
|
||||||
#endif // (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Define CONTINUABLE_HAS_EXCEPTIONS when exceptions are used
|
/// Define CONTINUABLE_HAS_EXCEPTIONS when exceptions are used
|
||||||
@ -130,18 +97,6 @@
|
|||||||
#else
|
#else
|
||||||
#undef CONTINUABLE_HAS_EXCEPTIONS
|
#undef CONTINUABLE_HAS_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Define CONTINUABLE_HAS_IMMEDIATE_TYPES when either
|
|
||||||
/// - CONTINUABLE_WITH_IMMEDIATE_TYPES is defined
|
|
||||||
/// - Building in release mode (NDEBUG is defined)
|
|
||||||
///
|
|
||||||
/// Build error messages will become more readable in debug mode while
|
|
||||||
/// we don't suffer any runtime penalty in release.
|
|
||||||
#if defined(CONTINUABLE_WITH_IMMEDIATE_TYPES) || defined(NDEBUG)
|
|
||||||
#define CONTINUABLE_HAS_IMMEDIATE_TYPES 1
|
|
||||||
#else
|
|
||||||
#undef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
|
||||||
#endif
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED
|
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED
|
||||||
|
|||||||
357
include/continuable/detail/flat-variant.hpp
Normal file
357
include/continuable/detail/flat-variant.hpp
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_FLAT_VARIANT_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_FLAT_VARIANT_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace container {
|
||||||
|
namespace detail {
|
||||||
|
// We don't want to pull the algorithm header in
|
||||||
|
template <typename... T>
|
||||||
|
constexpr std::size_t max_element_of(std::initializer_list<std::size_t> list) {
|
||||||
|
std::size_t m = 0;
|
||||||
|
for (auto current : list) {
|
||||||
|
if (current > m) {
|
||||||
|
m = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
template <typename... T>
|
||||||
|
constexpr auto storage_of_impl() {
|
||||||
|
constexpr auto size = max_element_of({sizeof(T)...});
|
||||||
|
constexpr auto align = max_element_of({alignof(T)...});
|
||||||
|
return std::aligned_storage_t<size, align>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declares the aligned storage union for the given types
|
||||||
|
template <typename... T>
|
||||||
|
using storage_of_t = decltype(storage_of_impl<T...>());
|
||||||
|
|
||||||
|
/// The value fpr the empty slot
|
||||||
|
using slot_t = std::uint8_t;
|
||||||
|
|
||||||
|
/// The value which is used to mark the empty slot
|
||||||
|
using empty_slot =
|
||||||
|
std::integral_constant<slot_t, std::numeric_limits<slot_t>::max()>;
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct flat_variant_base {
|
||||||
|
storage_of_t<T...> storage_;
|
||||||
|
slot_t slot_;
|
||||||
|
|
||||||
|
constexpr flat_variant_base() : slot_(empty_slot::value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
flat_variant_base(flat_variant_base const&) noexcept {
|
||||||
|
}
|
||||||
|
flat_variant_base(flat_variant_base&&) noexcept {
|
||||||
|
}
|
||||||
|
flat_variant_base& operator=(flat_variant_base const&) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
flat_variant_base& operator=(flat_variant_base&&) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Base>
|
||||||
|
struct flat_variant_move_base {
|
||||||
|
constexpr flat_variant_move_base() = default;
|
||||||
|
|
||||||
|
flat_variant_move_base(flat_variant_move_base const&) = default;
|
||||||
|
explicit flat_variant_move_base(flat_variant_move_base&& right) {
|
||||||
|
Base& me = *static_cast<Base*>(this);
|
||||||
|
Base& other = *static_cast<Base*>(&right);
|
||||||
|
|
||||||
|
if (other.is_empty()) {
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
other.visit([&](auto&& value) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
#endif
|
||||||
|
// NOLINTNEXTLINE(misc-move-forwarding-reference)
|
||||||
|
me.init(std::move(value), other.get_slot());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
other.destroy();
|
||||||
|
}
|
||||||
|
flat_variant_move_base& operator=(flat_variant_move_base const&) = default;
|
||||||
|
flat_variant_move_base& operator=(flat_variant_move_base&& right) {
|
||||||
|
Base& me = *static_cast<Base*>(this);
|
||||||
|
Base& other = *static_cast<Base*>(&right);
|
||||||
|
|
||||||
|
me.weak_destroy();
|
||||||
|
|
||||||
|
if (other.is_empty()) {
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
} else {
|
||||||
|
other.visit([&](auto&& value) {
|
||||||
|
// ...
|
||||||
|
me.init(std::move(value), other.get_slot());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
other.destroy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename Base, bool IsCopyable /*= true*/>
|
||||||
|
struct flat_variant_copy_base : flat_variant_move_base<Base> {
|
||||||
|
constexpr flat_variant_copy_base() = default;
|
||||||
|
|
||||||
|
flat_variant_copy_base(flat_variant_copy_base&&) = default;
|
||||||
|
explicit flat_variant_copy_base(flat_variant_copy_base const& right)
|
||||||
|
: flat_variant_move_base<Base>()
|
||||||
|
// TODO noexcept(Base::is_nothrow_move_constructible)
|
||||||
|
{
|
||||||
|
Base& me = *static_cast<Base*>(this);
|
||||||
|
Base const& other = *static_cast<Base const*>(&right);
|
||||||
|
|
||||||
|
if (other.is_empty()) {
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
} else {
|
||||||
|
other.visit([&](auto&& value) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
#endif
|
||||||
|
me.init(std::move(value), other.get_slot());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flat_variant_copy_base& operator=(flat_variant_copy_base&&) = default;
|
||||||
|
flat_variant_copy_base& operator=(flat_variant_copy_base const& right)
|
||||||
|
// TODO noexcept(Base::is_nothrow_move_constructible)
|
||||||
|
{
|
||||||
|
Base& me = *static_cast<Base*>(this);
|
||||||
|
Base const& other = *static_cast<Base const*>(&right);
|
||||||
|
|
||||||
|
me.weak_destroy();
|
||||||
|
|
||||||
|
if (other.is_empty()) {
|
||||||
|
me.set_slot(empty_slot::value);
|
||||||
|
} else {
|
||||||
|
other.visit([&](auto&& value) {
|
||||||
|
// ...
|
||||||
|
me.init(std::move(value), other.get_slot());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <typename Base /*, bool IsCopyable = false*/>
|
||||||
|
struct flat_variant_copy_base<Base, false> : flat_variant_move_base<Base> {
|
||||||
|
constexpr flat_variant_copy_base() = default;
|
||||||
|
|
||||||
|
flat_variant_copy_base(flat_variant_copy_base const&) = delete;
|
||||||
|
explicit flat_variant_copy_base(flat_variant_copy_base&& right) = default;
|
||||||
|
flat_variant_copy_base& operator=(flat_variant_copy_base const&) = delete;
|
||||||
|
flat_variant_copy_base& operator=(flat_variant_copy_base&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Deduces to a true_type if all parameters T satisfy the predicate.
|
||||||
|
template <template <typename> class Predicate, typename... T>
|
||||||
|
using every = traits::conjunction<Predicate<T>...>;
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// A class similar to the one in the variant proposal,
|
||||||
|
/// however it is capable of carrying an empty state by default.
|
||||||
|
template <typename... T>
|
||||||
|
class flat_variant;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_flat_variant : std::false_type {};
|
||||||
|
template <typename... T>
|
||||||
|
struct is_flat_variant<flat_variant<T...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
class flat_variant
|
||||||
|
: detail::flat_variant_copy_base<
|
||||||
|
flat_variant<T...>,
|
||||||
|
detail::every<std::is_copy_constructible, T...>::value>,
|
||||||
|
detail::flat_variant_base<T...> {
|
||||||
|
|
||||||
|
static_assert(sizeof...(T) > 0, "At least one paremeter T is required!");
|
||||||
|
|
||||||
|
template <typename...>
|
||||||
|
friend class flat_variant;
|
||||||
|
template <typename>
|
||||||
|
friend struct detail::flat_variant_move_base;
|
||||||
|
template <typename, bool>
|
||||||
|
friend struct detail::flat_variant_copy_base;
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
flat_variant(V&& value, detail::slot_t const slot) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
set_slot(detail::empty_slot::value);
|
||||||
|
#endif
|
||||||
|
init(std::forward<V>(value), slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr flat_variant() = default;
|
||||||
|
flat_variant(flat_variant const&) = default;
|
||||||
|
flat_variant(flat_variant&&) = default;
|
||||||
|
flat_variant& operator=(flat_variant const&) = default;
|
||||||
|
flat_variant& operator=(flat_variant&&) = default;
|
||||||
|
|
||||||
|
~flat_variant() noexcept(
|
||||||
|
detail::every<std::is_nothrow_destructible, T...>::value) {
|
||||||
|
weak_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename V,
|
||||||
|
std::enable_if_t<!is_flat_variant<std::decay_t<V>>::value>* = nullptr>
|
||||||
|
// Since the flat_variant isn't allowed through SFINAE
|
||||||
|
// this overload is safed against the linted issue.
|
||||||
|
// NOLINTNEXTLINE(misc-forwarding-reference-overload)
|
||||||
|
explicit flat_variant(V&& value)
|
||||||
|
: flat_variant(std::forward<V>(value),
|
||||||
|
traits::index_of_t<std::decay_t<V>, T...>::value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename V,
|
||||||
|
std::enable_if_t<!is_flat_variant<std::decay_t<V>>::value>* = nullptr>
|
||||||
|
flat_variant& operator=(V&& value) {
|
||||||
|
weak_destroy();
|
||||||
|
init(std::forward<V>(value),
|
||||||
|
traits::index_of_t<std::decay_t<V>, T...>::value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V, std::size_t Index =
|
||||||
|
traits::index_of_t<std::decay_t<V>, T...>::value>
|
||||||
|
bool is() const noexcept {
|
||||||
|
return is_slot(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_empty() const noexcept {
|
||||||
|
return is_slot(detail::empty_slot::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit constexpr operator bool() const noexcept {
|
||||||
|
return !is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
V& cast() noexcept {
|
||||||
|
assert(is_slot(traits::index_of_t<std::decay_t<V>, T...>::value));
|
||||||
|
return *reinterpret_cast<std::decay_t<V>*>(&this->storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
V const& cast() const noexcept {
|
||||||
|
assert(is_slot(traits::index_of_t<std::decay_t<V>, T...>::value));
|
||||||
|
return *reinterpret_cast<std::decay_t<V> const*>(&this->storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename C, typename V>
|
||||||
|
static void visit_dispatch(flat_variant* me, V&& visitor) {
|
||||||
|
std::forward<V>(visitor)(me->cast<C>());
|
||||||
|
}
|
||||||
|
template <typename C, typename V>
|
||||||
|
static void visit_dispatch_const(flat_variant const* me, V&& visitor) {
|
||||||
|
std::forward<V>(visitor)(me->cast<C>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
void visit(V&& visitor) {
|
||||||
|
if (!is_empty()) {
|
||||||
|
using callback_t = void (*)(flat_variant*, V &&);
|
||||||
|
constexpr callback_t const callbacks[] = {&visit_dispatch<T, V>...};
|
||||||
|
callbacks[get_slot()](this, std::forward<V>(visitor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
void visit(V&& visitor) const {
|
||||||
|
if (!is_empty()) {
|
||||||
|
using callback_t = void (*)(flat_variant const*, V&&);
|
||||||
|
constexpr callback_t const callbacks[] = {&visit_dispatch_const<T, V>...};
|
||||||
|
callbacks[get_slot()](this, std::forward<V>(visitor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
void init(V&& value, detail::slot_t const slot) {
|
||||||
|
assert(is_empty());
|
||||||
|
assert(sizeof(this->storage_) >= sizeof(std::decay_t<V>));
|
||||||
|
|
||||||
|
using type = std::decay_t<V>;
|
||||||
|
new (&this->storage_) type(std::forward<V>(value));
|
||||||
|
set_slot(slot);
|
||||||
|
}
|
||||||
|
void destroy() {
|
||||||
|
weak_destroy();
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
set_slot(detail::empty_slot::value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void weak_destroy() {
|
||||||
|
visit([&](auto&& value) {
|
||||||
|
using type = std::decay_t<decltype(value)>;
|
||||||
|
value.~type();
|
||||||
|
});
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
set_slot(detail::empty_slot::value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
detail::slot_t get_slot() const noexcept {
|
||||||
|
return this->slot_;
|
||||||
|
}
|
||||||
|
bool is_slot(detail::slot_t const slot) const noexcept {
|
||||||
|
return get_slot() == slot;
|
||||||
|
}
|
||||||
|
void set_slot(detail::slot_t const slot) {
|
||||||
|
this->slot_ = slot;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace container
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_FLAT_VARIANT_HPP_INCLUDED
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,33 +21,51 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_ANNOTATION_HPP_INCLUDED
|
#ifndef CONTINUABLE_DETAIL_HINTS_HPP_INCLUDED
|
||||||
#define CONTINUABLE_DETAIL_ANNOTATION_HPP_INCLUDED
|
#define CONTINUABLE_DETAIL_HINTS_HPP_INCLUDED
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
namespace hints {
|
namespace hints {
|
||||||
|
/// Represents a present signature hint
|
||||||
|
template <typename... Args>
|
||||||
|
using signature_hint_tag = traits::identity<Args...>;
|
||||||
|
|
||||||
|
/// Returns the signature hint of the given continuable
|
||||||
|
template <typename Data, typename... Args>
|
||||||
|
constexpr auto
|
||||||
|
hint_of(traits::identity<continuable_base<Data, signature_hint_tag<Args...>>>) {
|
||||||
|
return hints::signature_hint_tag<Args...>{};
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracts the signature we pass to the internal continuable
|
/// Extracts the signature we pass to the internal continuable
|
||||||
/// from an argument pack as specified by make_continuable.
|
/// from an argument pack as specified by make_continuable.
|
||||||
///
|
///
|
||||||
/// This is the overload taking an arbitrary amount of args
|
/// This is the overload taking an arbitrary amount of args
|
||||||
template <typename... HintArgs>
|
template <typename... HintArgs>
|
||||||
struct from_args : std::common_type<signature_arg_t<HintArgs...>> {};
|
constexpr auto extract(traits::identity<HintArgs...> hint) {
|
||||||
template <>
|
return hint;
|
||||||
struct from_args<void> : std::common_type<signature_arg_t<>> {};
|
}
|
||||||
|
/// \copybrief extract
|
||||||
|
///
|
||||||
|
/// This is the overload taking a void arg.
|
||||||
|
constexpr auto extract(traits::identity<void> /*hint*/) {
|
||||||
|
return traits::identity<>{};
|
||||||
|
}
|
||||||
} // namespace hints
|
} // namespace hints
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_ANNOTATION_HPP_INCLUDED
|
#endif // CONTINUABLE_DETAIL_HINTS_HPP_INCLUDED
|
||||||
@ -1,80 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/utility/identity.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace operations {
|
|
||||||
template <typename Callable, typename Executor, typename... Args>
|
|
||||||
auto async(Callable&& callable, Executor&& executor, Args&&... args) {
|
|
||||||
using result_t =
|
|
||||||
decltype(util::invoke(std::forward<decltype(callable)>(callable),
|
|
||||||
std::forward<decltype(args)>(args)...));
|
|
||||||
|
|
||||||
constexpr auto hint =
|
|
||||||
decltype(base::decoration::invoker_of(identity<result_t>{}))::hint();
|
|
||||||
|
|
||||||
auto continuation = [callable = std::forward<decltype(callable)>(callable),
|
|
||||||
executor = std::forward<decltype(executor)>(executor),
|
|
||||||
args = std::make_tuple(std::forward<decltype(args)>(
|
|
||||||
args)...)](auto&& promise) mutable {
|
|
||||||
auto invoker = base::decoration::invoker_of(identity<result_t>{});
|
|
||||||
|
|
||||||
using promise_t = decltype(promise);
|
|
||||||
|
|
||||||
// Invoke the callback
|
|
||||||
traits::unpack(
|
|
||||||
[&](auto&&... args) mutable {
|
|
||||||
// Invoke the promise through the dedicated invoker
|
|
||||||
// and through the given executor
|
|
||||||
base::on_executor(std::move(executor), std::move(invoker),
|
|
||||||
std::move(callable),
|
|
||||||
std::forward<promise_t>(promise),
|
|
||||||
std::forward<decltype(args)>(args)...);
|
|
||||||
},
|
|
||||||
std::move(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
return base::attorney::create_from(std::move(continuation), //
|
|
||||||
hint, util::ownership{});
|
|
||||||
}
|
|
||||||
} // namespace operations
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <memory>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
#include <exception>
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
template <typename T>
|
|
||||||
struct loop_trait {
|
|
||||||
static_assert(!std::is_same<T, T>::value,
|
|
||||||
"The callable passed to cti::loop must always return a "
|
|
||||||
"cti::continuable_base which resolves to a cti::result.");
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
struct loop_trait<identity<result<Args...>>> {
|
|
||||||
template <typename Callable>
|
|
||||||
static auto make(Callable&& callable) {
|
|
||||||
return make_continuable<Args...>(std::forward<Callable>(callable));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct loop_trait<identity<result<>>> {
|
|
||||||
template <typename Callable>
|
|
||||||
static auto make(Callable&& callable) {
|
|
||||||
return make_continuable<void>(std::forward<Callable>(callable));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace operations {
|
|
||||||
template <typename Promise, typename Callable, typename ArgsTuple>
|
|
||||||
class loop_frame : public std::enable_shared_from_this<
|
|
||||||
loop_frame<Promise, Callable, ArgsTuple>> {
|
|
||||||
Promise promise_;
|
|
||||||
Callable callable_;
|
|
||||||
ArgsTuple args_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit loop_frame(Promise promise, Callable callable, ArgsTuple args)
|
|
||||||
: promise_(std::move(promise)), callable_(std::move(callable)),
|
|
||||||
args_(std::move(args)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// MSVC can't evaluate this inside the lambda capture
|
|
||||||
auto me = this->shared_from_this();
|
|
||||||
|
|
||||||
traits::unpack(
|
|
||||||
[&](auto&&... args) mutable {
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
try {
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
util::invoke(callable_, std::forward<decltype(args)>(args)...)
|
|
||||||
.next([me = std::move(me)](auto&&... args) {
|
|
||||||
me->resolve(std::forward<decltype(args)>(args)...);
|
|
||||||
});
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
} catch (...) {
|
|
||||||
me->resolve(exception_arg_t{}, std::current_exception());
|
|
||||||
}
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
},
|
|
||||||
args_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Result>
|
|
||||||
void resolve(Result&& result) {
|
|
||||||
if (result.is_empty()) {
|
|
||||||
loop();
|
|
||||||
} else if (result.is_value()) {
|
|
||||||
traits::unpack(std::move(promise_), std::forward<Result>(result));
|
|
||||||
} else {
|
|
||||||
assert(result.is_exception());
|
|
||||||
std::move(promise_).set_exception(
|
|
||||||
std::forward<Result>(result).get_exception());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resolve(exception_arg_t, exception_t exception) {
|
|
||||||
promise_.set_exception(std::move(exception));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Promise, typename Callable, typename ArgsTuple>
|
|
||||||
auto make_loop_frame(Promise&& promise, Callable&& callable,
|
|
||||||
ArgsTuple&& args_tuple) {
|
|
||||||
using frame_t =
|
|
||||||
loop_frame<traits::unrefcv_t<Promise>, traits::unrefcv_t<Callable>,
|
|
||||||
traits::unrefcv_t<ArgsTuple>>;
|
|
||||||
|
|
||||||
return std::make_shared<frame_t>(std::forward<Promise>(promise),
|
|
||||||
std::forward<Callable>(callable),
|
|
||||||
std::forward<ArgsTuple>(args_tuple));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable, typename... Args>
|
|
||||||
auto loop(Callable&& callable, Args&&... args) {
|
|
||||||
using invocation_result_t =
|
|
||||||
decltype(util::invoke(callable, args...).finish());
|
|
||||||
|
|
||||||
auto constexpr hint = base::annotation_of(identify<invocation_result_t>{});
|
|
||||||
|
|
||||||
using trait_t = loop_trait<std::remove_const_t<decltype(hint)>>;
|
|
||||||
|
|
||||||
return trait_t::make([callable = std::forward<decltype(callable)>(callable),
|
|
||||||
args = std::make_tuple(std::forward<decltype(args)>(
|
|
||||||
args)...)](auto&& promise) mutable {
|
|
||||||
// Do the actual looping
|
|
||||||
auto frame = make_loop_frame(std::forward<decltype(promise)>(promise),
|
|
||||||
std::move(callable), std::move(args));
|
|
||||||
frame->loop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable, typename Begin, typename End>
|
|
||||||
auto make_range_looper(Callable&& callable, Begin&& begin, End&& end) {
|
|
||||||
return [callable = std::forward<Callable>(callable),
|
|
||||||
begin = std::forward<Begin>(begin),
|
|
||||||
end = std::forward<End>(end)]() mutable {
|
|
||||||
return util::invoke(callable, begin)
|
|
||||||
.then([&begin, &end]() mutable -> plain_t<result<>> {
|
|
||||||
// begin and end stays valid over the `then` here
|
|
||||||
if (++begin != end) {
|
|
||||||
return make_plain(result<>::empty());
|
|
||||||
} else {
|
|
||||||
return make_plain(make_result());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} // namespace operations
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-traverse.hpp>
|
|
||||||
#include <continuable/continuable-types.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace operations {
|
|
||||||
template <typename T, bool Else, typename = void>
|
|
||||||
struct operator_bool_or {
|
|
||||||
template <typename O>
|
|
||||||
static bool get(O&& /*obj*/) noexcept {
|
|
||||||
return Else;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename T, bool Else>
|
|
||||||
struct operator_bool_or<T, Else,
|
|
||||||
traits::void_t<decltype(bool(std::declval<T&>()))>> {
|
|
||||||
template <typename O>
|
|
||||||
static bool get(O&& obj) noexcept {
|
|
||||||
return bool(obj);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename First, typename... Promises>
|
|
||||||
class split_promise {
|
|
||||||
First first_;
|
|
||||||
std::tuple<Promises...> promises_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit split_promise(First first, Promises... promises)
|
|
||||||
: first_(std::move(first)), promises_(std::move(promises)...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void operator()(Args&&... args) && {
|
|
||||||
traverse_pack(
|
|
||||||
[&](auto&& promise) mutable -> void {
|
|
||||||
using accessor =
|
|
||||||
operator_bool_or<traits::unrefcv_t<decltype(promise)>, true>;
|
|
||||||
if (accessor::get(promise)) {
|
|
||||||
std::forward<decltype(promise)>(promise)(args...);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
std::move(promises_));
|
|
||||||
|
|
||||||
if (operator_bool_or<First, true>::get(first_)) {
|
|
||||||
std::move(first_)(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void set_value(Args... args) noexcept {
|
|
||||||
std::move (*this)(std::move(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_exception(exception_t error) noexcept {
|
|
||||||
std::move (*this)(exception_arg_t{}, std::move(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_canceled() noexcept {
|
|
||||||
std::move (*this)(exception_arg_t{}, exception_t{});
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
bool is_valid = operator_bool_or<First, true>::get(first_);
|
|
||||||
traverse_pack(
|
|
||||||
[&](auto&& promise) mutable -> void {
|
|
||||||
using accessor =
|
|
||||||
operator_bool_or<traits::unrefcv_t<decltype(promise)>, true>;
|
|
||||||
if (!is_valid && accessor::get(promise)) {
|
|
||||||
is_valid = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
promises_);
|
|
||||||
return is_valid;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace operations
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
@ -1,273 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
// Exclude this header when coroutines are not available
|
|
||||||
#ifndef CONTINUABLE_DETAIL_AWAITING_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_AWAITING_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
# include <experimental/coroutine>
|
|
||||||
#elif defined(CONTINUABLE_HAS_COROUTINE)
|
|
||||||
# include <coroutine>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_COROUTINE)
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace awaiting {
|
|
||||||
/// We import the coroutine handle in our namespace
|
|
||||||
# if defined(CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE)
|
|
||||||
using std::experimental::coroutine_handle;
|
|
||||||
using std::experimental::suspend_never;
|
|
||||||
# else
|
|
||||||
using std::coroutine_handle;
|
|
||||||
using std::suspend_never;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
class await_canceled_exception : public std::exception {
|
|
||||||
public:
|
|
||||||
await_canceled_exception() noexcept = default;
|
|
||||||
|
|
||||||
char const* what() const noexcept override {
|
|
||||||
return "co_await canceled due to cancellation of the continuation";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
# endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct result_from_identity;
|
|
||||||
template <typename... T>
|
|
||||||
struct result_from_identity<identity<T...>> {
|
|
||||||
using result_t = result<T...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// An object which provides the internal buffer and helper methods
|
|
||||||
/// for waiting on a continuable in a stackless coroutine.
|
|
||||||
template <typename Continuable>
|
|
||||||
class awaitable {
|
|
||||||
using hint_t = decltype(base::annotation_of(identify<Continuable>{}));
|
|
||||||
using result_t = typename result_from_identity<hint_t>::result_t;
|
|
||||||
|
|
||||||
/// The continuable which is invoked upon suspension
|
|
||||||
Continuable continuable_;
|
|
||||||
/// A cache which is used to pass the result of the continuation
|
|
||||||
/// to the coroutine.
|
|
||||||
result_t result_;
|
|
||||||
/// Enumeration that represents the suspension state of the awaitable.
|
|
||||||
enum class state : std::uint8_t {
|
|
||||||
suspended,
|
|
||||||
pending,
|
|
||||||
resolved,
|
|
||||||
};
|
|
||||||
/// An atomic that specifies whether the awaitable has suspended or not.
|
|
||||||
/// Allows to perform symmetric transfer on continuables that are
|
|
||||||
/// immediately resolved.
|
|
||||||
std::atomic<state> state_{state::pending};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit constexpr awaitable(Continuable&& continuable)
|
|
||||||
: continuable_(std::move(continuable)) {
|
|
||||||
|
|
||||||
// If the continuable is ready resolve the result from the
|
|
||||||
// continuable immediately.
|
|
||||||
if (base::attorney::is_ready(continuable_)) {
|
|
||||||
assert(result_.is_empty());
|
|
||||||
result_ = base::attorney::query(std::move(continuable_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return whether the continuable can provide its result instantly,
|
|
||||||
/// which also means its execution is side-effect free.
|
|
||||||
bool await_ready() const noexcept {
|
|
||||||
return !result_.is_empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Suspend the current context
|
|
||||||
// TODO Convert this to an r-value function once possible
|
|
||||||
bool await_suspend(coroutine_handle<> h) {
|
|
||||||
assert(result_.is_empty());
|
|
||||||
// Forward every result to the current awaitable
|
|
||||||
std::move(continuable_)
|
|
||||||
.next([h, this](auto&&... args) mutable {
|
|
||||||
assert(result_.is_empty());
|
|
||||||
result_ = result_t::from(std::forward<decltype(args)>(args)...);
|
|
||||||
|
|
||||||
// If true, it means that the promise was suspended (i.e., the
|
|
||||||
// awaitable await_suspend method has already returned). That
|
|
||||||
// means we must call the resume coroutine from the continuation
|
|
||||||
// chain.
|
|
||||||
if (state_.exchange(state::resolved, std::memory_order_acq_rel) ==
|
|
||||||
state::suspended) {
|
|
||||||
return h.resume();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.done();
|
|
||||||
|
|
||||||
return state_.exchange(state::suspended, std::memory_order_acq_rel) !=
|
|
||||||
state::resolved;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resume the coroutine represented by the handle
|
|
||||||
typename result_t::value_t await_resume() noexcept(false) {
|
|
||||||
if (result_.is_value()) {
|
|
||||||
// When the result was resolved return it
|
|
||||||
return std::move(result_).get_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(result_.is_exception());
|
|
||||||
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
if (exception_t e = result_.get_exception()) {
|
|
||||||
std::rethrow_exception(std::move(e));
|
|
||||||
} else {
|
|
||||||
throw await_canceled_exception();
|
|
||||||
}
|
|
||||||
# else // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
// Returning error types from co_await isn't supported!
|
|
||||||
CTI_DETAIL_TRAP();
|
|
||||||
# endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Converts a continuable into an awaitable object as described by
|
|
||||||
/// the C++ coroutine TS.
|
|
||||||
template <typename T>
|
|
||||||
constexpr auto create_awaiter(T&& continuable) {
|
|
||||||
return awaitable<std::decay_t<T>>(std::forward<T>(continuable));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This makes it possible to take the coroutine_handle over on suspension
|
|
||||||
struct handle_takeover {
|
|
||||||
coroutine_handle<>& handle_;
|
|
||||||
|
|
||||||
bool await_ready() noexcept {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void await_suspend(coroutine_handle<> handle) noexcept {
|
|
||||||
handle_ = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void await_resume() noexcept {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The type which is passed to the compiler that describes the properties
|
|
||||||
/// of a continuable_base used as coroutine promise type.
|
|
||||||
template <typename Continuable, typename Promise, typename... Args>
|
|
||||||
struct promise_type;
|
|
||||||
|
|
||||||
/// Implements the resolving method return_void and return_value accordingly
|
|
||||||
template <typename Base>
|
|
||||||
struct promise_resolver_base;
|
|
||||||
|
|
||||||
template <typename Continuable, typename Promise>
|
|
||||||
struct promise_resolver_base<promise_type<Continuable, Promise>> {
|
|
||||||
void return_void() {
|
|
||||||
auto me = static_cast<promise_type<Continuable, Promise>*>(this);
|
|
||||||
me->promise_.set_value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename Continuable, typename Promise, typename T>
|
|
||||||
struct promise_resolver_base<promise_type<Continuable, Promise, T>> {
|
|
||||||
void return_value(T value) {
|
|
||||||
auto me = static_cast<promise_type<Continuable, Promise, T>*>(this);
|
|
||||||
me->promise_.set_value(std::move(value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename Continuable, typename Promise, typename... Args>
|
|
||||||
struct promise_resolver_base<promise_type<Continuable, Promise, Args...>> {
|
|
||||||
template <typename T>
|
|
||||||
void return_value(T&& tuple_like) {
|
|
||||||
auto me = static_cast<promise_type<Continuable, Promise, Args...>*>(this);
|
|
||||||
traits::unpack(std::move(me->promise_), std::forward<T>(tuple_like));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Continuable, typename Promise, typename... Args>
|
|
||||||
struct promise_type
|
|
||||||
: promise_resolver_base<promise_type<Continuable, Promise, Args...>> {
|
|
||||||
|
|
||||||
coroutine_handle<> handle_;
|
|
||||||
Promise promise_;
|
|
||||||
|
|
||||||
explicit promise_type() = default;
|
|
||||||
|
|
||||||
Continuable get_return_object() {
|
|
||||||
return [this](auto&& promise) {
|
|
||||||
promise_ = std::forward<decltype(promise)>(promise);
|
|
||||||
handle_.resume();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_takeover initial_suspend() {
|
|
||||||
return {handle_};
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend_never final_suspend() noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void unhandled_exception() noexcept {
|
|
||||||
# if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(std::current_exception());
|
|
||||||
} catch (await_canceled_exception const&) {
|
|
||||||
promise_.set_canceled();
|
|
||||||
} catch (...) {
|
|
||||||
promise_.set_exception(std::current_exception());
|
|
||||||
}
|
|
||||||
# else // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
// Returning exception types from a coroutine isn't supported
|
|
||||||
CTI_DETAIL_TRAP();
|
|
||||||
# endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace awaiting
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
#endif // defined(CONTINUABLE_HAS_COROUTINE)
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
|
||||||
@ -1,241 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <function2/function2.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace erasure {
|
|
||||||
template <typename... Args>
|
|
||||||
using callback_erasure_t =
|
|
||||||
fu2::function_base<true, false, fu2::capacity_none, true, false,
|
|
||||||
void(Args...)&&, void(exception_arg_t, exception_t) &&>;
|
|
||||||
|
|
||||||
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
|
||||||
template <typename... Args>
|
|
||||||
using callback = callback_erasure_t<Args...>;
|
|
||||||
#else
|
|
||||||
template <typename... Args>
|
|
||||||
class callback;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_callback : std::false_type {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct is_callback<callback<Args...>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
class callback : public callback_erasure_t<Args...> {
|
|
||||||
public:
|
|
||||||
using erasure_t = callback_erasure_t<Args...>;
|
|
||||||
erasure_t erasure_;
|
|
||||||
|
|
||||||
callback() = default;
|
|
||||||
~callback() = default;
|
|
||||||
callback(callback const&) = delete;
|
|
||||||
callback(callback&&) = default;
|
|
||||||
callback& operator=(callback const&) = delete;
|
|
||||||
callback& operator=(callback&&) = default;
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
|
||||||
/* implicit */ callback(T&& callable) : erasure_(std::forward<T>(callable)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
|
||||||
callback& operator=(T&& callable) {
|
|
||||||
erasure_ = std::forward<T>(callable);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(Args... args) && noexcept {
|
|
||||||
std::move(erasure_)(std::move(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(exception_arg_t exception_arg, exception_t exception) &&
|
|
||||||
noexcept {
|
|
||||||
std::move(erasure_)(exception_arg, std::move(exception));
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
return bool(erasure_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using work_erasure_t =
|
|
||||||
fu2::function_base<true, false, fu2::capacity_fixed<32UL>, true, false,
|
|
||||||
void()&&, void(exception_arg_t, exception_t) &&>;
|
|
||||||
|
|
||||||
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
|
||||||
using work = work_erasure_t;
|
|
||||||
#else
|
|
||||||
class work;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_work : std::false_type {};
|
|
||||||
template <>
|
|
||||||
struct is_work<work> : std::true_type {};
|
|
||||||
|
|
||||||
class work {
|
|
||||||
using erasure_t = work_erasure_t;
|
|
||||||
erasure_t erasure_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
work() = default;
|
|
||||||
~work() = default;
|
|
||||||
work(work const&) = delete;
|
|
||||||
work(work&&) = default;
|
|
||||||
work& operator=(work const&) = delete;
|
|
||||||
work& operator=(work&&) = default;
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_work<traits::unrefcv_t<T>>::value>* = nullptr>
|
|
||||||
/* implicit */ work(T&& callable) : erasure_(std::forward<T>(callable)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_work<traits::unrefcv_t<T>>::value>* = nullptr>
|
|
||||||
work& operator=(T&& callable) {
|
|
||||||
erasure_ = std::forward<T>(callable);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()() && noexcept {
|
|
||||||
std::move(erasure_)();
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(exception_arg_t, exception_t exception) && noexcept {
|
|
||||||
std::move(erasure_)(exception_arg_t{}, std::move(exception));
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
return bool(erasure_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
struct continuation_capacity {
|
|
||||||
using type = union {
|
|
||||||
void* pointer_;
|
|
||||||
base::ready_continuation<Args...> continuation_;
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr std::size_t capacity = sizeof(type);
|
|
||||||
static constexpr std::size_t alignment = alignof(type);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using continuation_erasure_t = fu2::function_base<
|
|
||||||
true, false, continuation_capacity<Args...>, true, false,
|
|
||||||
void(promise_base<callback<Args...>, signature_arg_t<Args...>>),
|
|
||||||
bool(is_ready_arg_t) const, result<Args...>(unpack_arg_t)>;
|
|
||||||
|
|
||||||
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
|
||||||
template <typename... Args>
|
|
||||||
using continuation = continuation_erasure_t<Args...>;
|
|
||||||
#else
|
|
||||||
template <typename... Args>
|
|
||||||
class continuation;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_continuation : std::false_type {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct is_continuation<continuation<Args...>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
class continuation {
|
|
||||||
using erasure_t = continuation_erasure_t<Args...>;
|
|
||||||
erasure_t erasure_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
continuation() = default;
|
|
||||||
~continuation() = default;
|
|
||||||
continuation(continuation const&) = delete;
|
|
||||||
continuation(continuation&&) = default;
|
|
||||||
continuation& operator=(continuation const&) = delete;
|
|
||||||
continuation& operator=(continuation&&) = default;
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
|
||||||
nullptr>
|
|
||||||
/* implicit */ continuation(T&& callable)
|
|
||||||
: erasure_(std::forward<T>(callable)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
|
||||||
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
|
||||||
nullptr>
|
|
||||||
continuation& operator=(T&& callable) {
|
|
||||||
erasure_ = std::forward<T>(callable);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(promise_base<callback<Args...>, //
|
|
||||||
signature_arg_t<Args...>>
|
|
||||||
promise) {
|
|
||||||
erasure_(std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(is_ready_arg_t is_ready_arg) const {
|
|
||||||
return erasure_(is_ready_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
result<Args...> operator()(unpack_arg_t query_arg) {
|
|
||||||
return erasure_(query_arg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
} // namespace erasure
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
#include <exception>
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace convert {
|
|
||||||
/// A resolver for promisifying asio and js style callbacks.
|
|
||||||
inline auto default_resolver() {
|
|
||||||
return [](auto&& promise, auto&& e, auto&&... args) {
|
|
||||||
static_assert(
|
|
||||||
std::is_convertible<std::decay_t<decltype(e)>, exception_t>::value,
|
|
||||||
"The given error type must be convertible to the error type used! "
|
|
||||||
"Specify a custom resolver in order to apply a conversion to the "
|
|
||||||
"used error type.");
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
promise.set_exception(std::forward<decltype(e)>(e));
|
|
||||||
} else {
|
|
||||||
promise.set_value(std::forward<decltype(args)>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Result>
|
|
||||||
struct promisify_helper {
|
|
||||||
template <typename Resolver, typename Callable, typename... Args>
|
|
||||||
static auto from(Resolver&& resolver, Callable&& callable, Args&&... args) {
|
|
||||||
return make_continuable<Result...>(
|
|
||||||
[resolver = std::forward<Resolver>(resolver),
|
|
||||||
args = traits::make_flat_tuple(std::forward<Callable>(callable),
|
|
||||||
std::forward<Args>(args)...)](
|
|
||||||
auto&& promise) mutable {
|
|
||||||
traits::unpack(
|
|
||||||
[promise = std::forward<decltype(promise)>(promise),
|
|
||||||
&resolver](auto&&... args) mutable {
|
|
||||||
// Call the resolver from with the promise and result
|
|
||||||
auto callback =
|
|
||||||
[resolver = std::move(resolver),
|
|
||||||
promise = std::move(promise)](auto&&... args) mutable {
|
|
||||||
resolver(std::move(promise),
|
|
||||||
std::forward<decltype(args)>(args)...);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invoke the callback taking function
|
|
||||||
util::invoke(std::forward<decltype(args)>(args)...,
|
|
||||||
std::move(callback));
|
|
||||||
},
|
|
||||||
std::move(args));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace convert
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
|
||||||
95
include/continuable/detail/promisify.hpp
Normal file
95
include/continuable/detail/promisify.hpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
#include <exception>
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
#include <continuable/continuable-base.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace convert {
|
||||||
|
/// A helper class for promisifying asio and js style callback
|
||||||
|
/// taking functions into a continuable.
|
||||||
|
template <typename P>
|
||||||
|
struct promisify_default {
|
||||||
|
P promise;
|
||||||
|
|
||||||
|
template <typename E, typename... T>
|
||||||
|
void operator()(E&& error, T&&... result) {
|
||||||
|
if (error) {
|
||||||
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
|
promise.set_exception(std::make_exception_ptr(std::forward<E>(error)));
|
||||||
|
#else
|
||||||
|
promise.set_exception(
|
||||||
|
std::error_condition(error.value(), error.category()));
|
||||||
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
} else {
|
||||||
|
promise.set_value(std::forward<T>(result)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Result>
|
||||||
|
struct promisify_helper {
|
||||||
|
template <template <class T> class Evaluator, typename Callable,
|
||||||
|
typename... Args>
|
||||||
|
static auto from(Callable&& callable, Args&&... args) {
|
||||||
|
return make_continuable<Result...>([args = std::make_tuple(
|
||||||
|
std::forward<Callable>(callable),
|
||||||
|
std::forward<Args>(args)...)](
|
||||||
|
auto&& promise) mutable {
|
||||||
|
|
||||||
|
traits::unpack(
|
||||||
|
std::move(args), [promise = std::forward<decltype(promise)>(promise)](
|
||||||
|
auto&&... args) mutable {
|
||||||
|
Evaluator<std::decay_t<decltype(promise)>> evaluator{
|
||||||
|
std::move(promise)};
|
||||||
|
|
||||||
|
util::invoke(std::forward<decltype(args)>(args)...,
|
||||||
|
std::move(evaluator));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace convert
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_PROMISIFY_HPP_INCLUDED
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -35,7 +35,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -33,12 +33,13 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -54,7 +55,7 @@ void assert_async_completion(C&& continuable) {
|
|||||||
// Workaround for our known GCC bug.
|
// Workaround for our known GCC bug.
|
||||||
util::unused(std::forward<decltype(args)>(args)...);
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
})
|
})
|
||||||
.fail([](cti::exception_t /*error*/) {
|
.fail([](cti::error_type /*error*/) {
|
||||||
// ...
|
// ...
|
||||||
FAIL();
|
FAIL();
|
||||||
});
|
});
|
||||||
@ -73,28 +74,7 @@ void assert_async_exception_completion(C&& continuable) {
|
|||||||
// ...
|
// ...
|
||||||
FAIL();
|
FAIL();
|
||||||
})
|
})
|
||||||
.fail([called](cti::exception_t error) {
|
.fail([called](cti::error_type /*error*/) {
|
||||||
ASSERT_TRUE(bool(error));
|
|
||||||
ASSERT_FALSE(*called);
|
|
||||||
*called = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
ASSERT_TRUE(*called);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
void assert_async_cancellation(C&& continuable) {
|
|
||||||
auto called = std::make_shared<bool>(false);
|
|
||||||
std::forward<C>(continuable)
|
|
||||||
.then([](auto&&... args) {
|
|
||||||
// Workaround for our known GCC bug.
|
|
||||||
util::unused(std::forward<decltype(args)>(args)...);
|
|
||||||
|
|
||||||
// ...
|
|
||||||
FAIL();
|
|
||||||
})
|
|
||||||
.fail([called](cti::exception_t error) {
|
|
||||||
ASSERT_FALSE(bool(error));
|
|
||||||
ASSERT_FALSE(*called);
|
ASSERT_FALSE(*called);
|
||||||
*called = true;
|
*called = true;
|
||||||
});
|
});
|
||||||
@ -111,7 +91,7 @@ void assert_async_never_completed(C&& continuable) {
|
|||||||
|
|
||||||
FAIL();
|
FAIL();
|
||||||
})
|
})
|
||||||
.fail([](cti::exception_t) {
|
.fail([](cti::error_type /*error*/) {
|
||||||
// ...
|
// ...
|
||||||
FAIL();
|
FAIL();
|
||||||
});
|
});
|
||||||
@ -121,10 +101,11 @@ template <typename C, typename V>
|
|||||||
void assert_async_validation(C&& continuable, V&& validator) {
|
void assert_async_validation(C&& continuable, V&& validator) {
|
||||||
assert_async_completion(
|
assert_async_completion(
|
||||||
std::forward<C>(continuable)
|
std::forward<C>(continuable)
|
||||||
.then(
|
.then([validator =
|
||||||
[validator = std::forward<V>(validator)](auto&&... args) mutable {
|
std::forward<V>(validator)](auto&&... args) mutable {
|
||||||
validator(std::forward<decltype(args)>(args)...);
|
|
||||||
}));
|
validator(std::forward<decltype(args)>(args)...);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expects that the continuable is finished with the given arguments
|
/// Expects that the continuable is finished with the given arguments
|
||||||
@ -134,17 +115,18 @@ void assert_async_binary_validation(V&& validator, C&& continuable,
|
|||||||
|
|
||||||
using size = std::integral_constant<std::size_t, sizeof...(expected)>;
|
using size = std::integral_constant<std::size_t, sizeof...(expected)>;
|
||||||
|
|
||||||
assert_async_validation(
|
assert_async_validation(std::forward<C>(continuable), [
|
||||||
std::forward<C>(continuable),
|
expected_pack = std::make_tuple(std::forward<Args>(expected)...),
|
||||||
[expected_pack = std::make_tuple(std::forward<Args>(expected)...),
|
validator = std::forward<V>(validator)
|
||||||
validator = std::forward<V>(validator)](auto&&... args) mutable {
|
](auto&&... args) mutable {
|
||||||
static_assert(size::value == sizeof...(args),
|
|
||||||
"Async completion handler called with a different count "
|
|
||||||
"of arguments!");
|
|
||||||
|
|
||||||
validator(std::make_tuple(std::forward<decltype(args)>(args)...),
|
static_assert(size::value == sizeof...(args),
|
||||||
expected_pack);
|
"Async completion handler called with a different count "
|
||||||
});
|
"of arguments!");
|
||||||
|
|
||||||
|
validator(std::make_tuple(std::forward<decltype(args)>(args)...),
|
||||||
|
expected_pack);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expects that the continuable is finished with the given arguments
|
/// Expects that the continuable is finished with the given arguments
|
||||||
@ -157,19 +139,20 @@ void assert_async_binary_exception_validation(V&& validator, C&& continuable,
|
|||||||
// Workaround for our known GCC bug.
|
// Workaround for our known GCC bug.
|
||||||
util::unused(std::forward<decltype(args)>(args)...);
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
// The exception was not thrown!
|
// ...
|
||||||
FAIL();
|
FAIL();
|
||||||
})
|
})
|
||||||
.fail([called, validator = std::forward<decltype(validator)>(validator),
|
.fail([
|
||||||
expected = std::forward<decltype(expected)>(expected)](
|
called, validator = std::forward<decltype(validator)>(validator),
|
||||||
exception_t error) {
|
expected = std::forward<decltype(expected)>(expected)
|
||||||
|
](types::error_type error) {
|
||||||
ASSERT_FALSE(*called);
|
ASSERT_FALSE(*called);
|
||||||
*called = true;
|
*called = true;
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
try {
|
try {
|
||||||
std::rethrow_exception(error);
|
std::rethrow_exception(error);
|
||||||
} catch (std::decay_t<decltype(expected)> const& exception) {
|
} catch (std::decay_t<decltype(expected)>& exception) {
|
||||||
validator(exception, expected);
|
validator(exception, expected);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
FAIL();
|
FAIL();
|
||||||
@ -200,14 +183,15 @@ template <typename... Expected>
|
|||||||
struct assert_async_types_validator {
|
struct assert_async_types_validator {
|
||||||
template <typename... Actual>
|
template <typename... Actual>
|
||||||
void operator()(Actual...) {
|
void operator()(Actual...) {
|
||||||
static_assert(
|
static_assert(std::is_same<traits::identity<Actual...>,
|
||||||
std::is_same<identity<Actual...>, identity<Expected...>>::value,
|
traits::identity<Expected...>>::value,
|
||||||
"The called arguments don't match with the expected ones!");
|
"The called arguments don't match with the expected ones!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C, typename... Args>
|
template <typename C, typename... Args>
|
||||||
void assert_async_types(C&& continuable, identity<Args...> /*expected*/) {
|
void assert_async_types(C&& continuable,
|
||||||
|
traits::identity<Args...> /*expected*/) {
|
||||||
assert_async_validation(std::forward<C>(continuable),
|
assert_async_validation(std::forward<C>(continuable),
|
||||||
assert_async_types_validator<Args...>{});
|
assert_async_types_validator<Args...>{});
|
||||||
}
|
}
|
||||||
358
include/continuable/detail/traits.hpp
Normal file
358
include/continuable/detail/traits.hpp
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
/~` _ _ _|_. _ _ |_ | _
|
||||||
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
|
https://github.com/Naios/continuable
|
||||||
|
v3.0.0
|
||||||
|
|
||||||
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions :
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
||||||
|
#define CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
|
||||||
|
namespace cti {
|
||||||
|
namespace detail {
|
||||||
|
namespace traits {
|
||||||
|
/// Evaluates to the element at position I.
|
||||||
|
template <std::size_t I, typename... Args>
|
||||||
|
using at_t = decltype(std::get<I>(std::declval<std::tuple<Args...>>()));
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
struct index_of_impl;
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
struct index_of_impl<T, T, Args...> : std::integral_constant<std::size_t, 0U> {
|
||||||
|
};
|
||||||
|
template <typename T, typename U, typename... Args>
|
||||||
|
struct index_of_impl<T, U, Args...>
|
||||||
|
: std::integral_constant<std::size_t,
|
||||||
|
1 + index_of_impl<T, Args...>::value> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Evaluates to the index of T in the given pack
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
using index_of_t = detail::index_of_impl<T, Args...>;
|
||||||
|
|
||||||
|
/// A tagging type for wrapping other types
|
||||||
|
template <typename... T>
|
||||||
|
struct identity {};
|
||||||
|
template <typename T>
|
||||||
|
struct identity<T> : std::common_type<T> {};
|
||||||
|
|
||||||
|
template <typename>
|
||||||
|
struct is_identity : std::false_type {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct is_identity<identity<Args...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr identity<std::decay_t<T>> identity_of(T const& /*type*/) noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
template <typename... Args>
|
||||||
|
constexpr identity<Args...> identity_of(identity<Args...> /*type*/) noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||||
|
identity<std::decay_t<T>>>;
|
||||||
|
|
||||||
|
template <std::size_t I, typename... T>
|
||||||
|
constexpr auto get(identity<T...>) noexcept {
|
||||||
|
return identify<at_t<I, T...>>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
// Equivalent to C++17's std::void_t which targets a bug in GCC,
|
||||||
|
// that prevents correct SFINAE behavior.
|
||||||
|
// See http://stackoverflow.com/questions/35753920 for details.
|
||||||
|
template <typename...>
|
||||||
|
struct deduce_to_void : std::common_type<void> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// C++17 like void_t type
|
||||||
|
template <typename... T>
|
||||||
|
using void_t = typename detail::deduce_to_void<T...>::type;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename Type, typename TrueCallback>
|
||||||
|
constexpr void static_if_impl(std::true_type, Type&& type,
|
||||||
|
TrueCallback&& trueCallback) {
|
||||||
|
std::forward<TrueCallback>(trueCallback)(std::forward<Type>(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, typename TrueCallback>
|
||||||
|
constexpr void static_if_impl(std::false_type, Type&& /*type*/,
|
||||||
|
TrueCallback&& /*trueCallback*/) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, typename TrueCallback, typename FalseCallback>
|
||||||
|
constexpr auto static_if_impl(std::true_type, Type&& type,
|
||||||
|
TrueCallback&& trueCallback,
|
||||||
|
FalseCallback&& /*falseCallback*/) {
|
||||||
|
return std::forward<TrueCallback>(trueCallback)(std::forward<Type>(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type, typename TrueCallback, typename FalseCallback>
|
||||||
|
constexpr auto static_if_impl(std::false_type, Type&& type,
|
||||||
|
TrueCallback&& /*trueCallback*/,
|
||||||
|
FalseCallback&& falseCallback) {
|
||||||
|
return std::forward<FalseCallback>(falseCallback)(std::forward<Type>(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluates to the size of the given tuple like type,
|
||||||
|
// / if the type has no static size it will be one.
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct tuple_like_size : std::integral_constant<std::size_t, 1U> {};
|
||||||
|
template <typename T>
|
||||||
|
struct tuple_like_size<T, void_t<decltype(std::tuple_size<T>::value)>>
|
||||||
|
: std::tuple_size<T> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Returns the pack size of the given empty pack
|
||||||
|
constexpr std::size_t pack_size_of(identity<>) noexcept {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
/// Returns the pack size of the given type
|
||||||
|
template <typename T>
|
||||||
|
constexpr std::size_t pack_size_of(identity<T>) noexcept {
|
||||||
|
return detail::tuple_like_size<T>::value;
|
||||||
|
}
|
||||||
|
/// Returns the pack size of the given type
|
||||||
|
template <typename First, typename Second, typename... Args>
|
||||||
|
constexpr std::size_t pack_size_of(identity<First, Second, Args...>) noexcept {
|
||||||
|
return 2U + sizeof...(Args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an index sequence of the given type
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto sequence_of(identity<T>) noexcept {
|
||||||
|
constexpr auto const size = pack_size_of(identity<T>{});
|
||||||
|
return std::make_index_sequence<size>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invokes the callback only if the given type matches the check
|
||||||
|
template <typename Type, typename Check, typename TrueCallback>
|
||||||
|
constexpr void static_if(Type&& type, Check&& check,
|
||||||
|
TrueCallback&& trueCallback) {
|
||||||
|
detail::static_if_impl(std::forward<Check>(check)(type),
|
||||||
|
std::forward<Type>(type),
|
||||||
|
std::forward<TrueCallback>(trueCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invokes the callback only if the given type matches the check
|
||||||
|
template <typename Type, typename Check, typename TrueCallback,
|
||||||
|
typename FalseCallback>
|
||||||
|
constexpr auto static_if(Type&& type, Check&& check,
|
||||||
|
TrueCallback&& trueCallback,
|
||||||
|
FalseCallback&& falseCallback) {
|
||||||
|
return detail::static_if_impl(std::forward<Check>(check)(type),
|
||||||
|
std::forward<Type>(type),
|
||||||
|
std::forward<TrueCallback>(trueCallback),
|
||||||
|
std::forward<FalseCallback>(falseCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls the given unpacker with the content of the given sequence
|
||||||
|
template <typename U, std::size_t... I>
|
||||||
|
constexpr decltype(auto) unpack(std::integer_sequence<std::size_t, I...>,
|
||||||
|
U&& unpacker) {
|
||||||
|
return std::forward<U>(unpacker)(std::integral_constant<std::size_t, I>{}...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls the given unpacker with the content of the given sequenceable
|
||||||
|
template <typename F, typename U, std::size_t... I>
|
||||||
|
constexpr auto unpack(F&& first_sequenceable, U&& unpacker,
|
||||||
|
std::integer_sequence<std::size_t, I...>)
|
||||||
|
-> decltype(std::forward<U>(unpacker)(
|
||||||
|
get<I>(std::forward<F>(first_sequenceable))...)) {
|
||||||
|
(void)first_sequenceable;
|
||||||
|
return std::forward<U>(unpacker)(
|
||||||
|
get<I>(std::forward<F>(first_sequenceable))...);
|
||||||
|
}
|
||||||
|
/// Calls the given unpacker with the content of the given sequenceable
|
||||||
|
template <typename F, typename S, typename U, std::size_t... If,
|
||||||
|
std::size_t... Is>
|
||||||
|
constexpr auto unpack(F&& first_sequenceable, S&& second_sequenceable,
|
||||||
|
U&& unpacker, std::integer_sequence<std::size_t, If...>,
|
||||||
|
std::integer_sequence<std::size_t, Is...>)
|
||||||
|
-> decltype(std::forward<U>(unpacker)(
|
||||||
|
get<If>(std::forward<F>(first_sequenceable))...,
|
||||||
|
get<Is>(std::forward<S>(second_sequenceable))...)) {
|
||||||
|
(void)first_sequenceable;
|
||||||
|
(void)second_sequenceable;
|
||||||
|
return std::forward<U>(unpacker)(
|
||||||
|
get<If>(std::forward<F>(first_sequenceable))...,
|
||||||
|
get<Is>(std::forward<S>(second_sequenceable))...);
|
||||||
|
}
|
||||||
|
/// Calls the given unpacker with the content of the given sequenceable
|
||||||
|
template <typename F, typename U>
|
||||||
|
constexpr auto unpack(F&& first_sequenceable, U&& unpacker)
|
||||||
|
-> decltype(unpack(std::forward<F>(first_sequenceable),
|
||||||
|
std::forward<U>(unpacker),
|
||||||
|
sequence_of(identify<decltype(first_sequenceable)>{}))) {
|
||||||
|
return unpack(std::forward<F>(first_sequenceable), std::forward<U>(unpacker),
|
||||||
|
sequence_of(identify<decltype(first_sequenceable)>{}));
|
||||||
|
}
|
||||||
|
/// Calls the given unpacker with the content of the given sequenceables
|
||||||
|
template <typename F, typename S, typename U>
|
||||||
|
constexpr auto unpack(F&& first_sequenceable, S&& second_sequenceable,
|
||||||
|
U&& unpacker)
|
||||||
|
-> decltype(unpack(std::forward<F>(first_sequenceable),
|
||||||
|
std::forward<S>(second_sequenceable),
|
||||||
|
std::forward<U>(unpacker),
|
||||||
|
sequence_of(identity_of(first_sequenceable)),
|
||||||
|
sequence_of(identity_of(second_sequenceable)))) {
|
||||||
|
return unpack(std::forward<F>(first_sequenceable),
|
||||||
|
std::forward<S>(second_sequenceable), std::forward<U>(unpacker),
|
||||||
|
sequence_of(identity_of(first_sequenceable)),
|
||||||
|
sequence_of(identity_of(second_sequenceable)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds the given type at the back of the left sequenceable
|
||||||
|
template <typename Left, typename Element>
|
||||||
|
constexpr auto push(Left&& left, Element&& element) {
|
||||||
|
return unpack(std::forward<Left>(left), [&](auto&&... args) {
|
||||||
|
return std::make_tuple(std::forward<decltype(args)>(args)...,
|
||||||
|
std::forward<Element>(element));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds the element to the back of the identity
|
||||||
|
template <typename... Args, typename Element>
|
||||||
|
constexpr auto push(identity<Args...>, identity<Element>) noexcept {
|
||||||
|
return identity<Args..., Element>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the first element from the identity
|
||||||
|
template <typename First, typename... Rest>
|
||||||
|
constexpr auto pop_first(identity<First, Rest...>) noexcept {
|
||||||
|
return identity<Rest...>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the merged sequence
|
||||||
|
template <typename Left>
|
||||||
|
constexpr auto merge(Left&& left) {
|
||||||
|
return std::forward<Left>(left);
|
||||||
|
}
|
||||||
|
/// Merges the left sequenceable with the right ones
|
||||||
|
template <typename Left, typename Right, typename... Rest>
|
||||||
|
constexpr auto merge(Left&& left, Right&& right, Rest&&... rest) {
|
||||||
|
// Merge the left with the right sequenceable and
|
||||||
|
// merge the result with the rest.
|
||||||
|
return merge(unpack(std::forward<Left>(left), std::forward<Right>(right),
|
||||||
|
[&](auto&&... args) {
|
||||||
|
// Maybe use: template <template<typename...> class T,
|
||||||
|
// typename... Args>
|
||||||
|
return std::make_tuple(
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
|
}),
|
||||||
|
std::forward<Rest>(rest)...);
|
||||||
|
}
|
||||||
|
/// Merges the left identity with the right ones
|
||||||
|
template <typename... LeftArgs, typename... RightArgs, typename... Rest>
|
||||||
|
constexpr auto merge(identity<LeftArgs...> /*left*/,
|
||||||
|
identity<RightArgs...> /*right*/, Rest&&... rest) {
|
||||||
|
return merge(identity<LeftArgs..., RightArgs...>{},
|
||||||
|
std::forward<Rest>(rest)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, typename Args, typename = traits::void_t<>>
|
||||||
|
struct is_invokable_impl : std::common_type<std::false_type> {};
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
struct is_invokable_impl<
|
||||||
|
T, std::tuple<Args...>,
|
||||||
|
void_t<decltype(std::declval<T>()(std::declval<Args>()...))>>
|
||||||
|
: std::common_type<std::true_type> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Deduces to a std::true_type if the given type is callable with the arguments
|
||||||
|
/// inside the given tuple.
|
||||||
|
/// The main reason for implementing it with the detection idiom instead of
|
||||||
|
/// hana like detection is that MSVC has issues with capturing raw template
|
||||||
|
/// arguments inside lambda closures.
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// traits::is_invokable<object, std::tuple<Args...>>
|
||||||
|
/// ```
|
||||||
|
template <typename T, typename Args>
|
||||||
|
using is_invokable_from_tuple =
|
||||||
|
typename detail::is_invokable_impl<T, Args>::type;
|
||||||
|
|
||||||
|
// Checks whether the given callable object is invocable with the given
|
||||||
|
// arguments. This doesn't take member functions into account!
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
using is_invocable = is_invokable_from_tuple<T, std::tuple<Args...>>;
|
||||||
|
|
||||||
|
/// Deduces to a std::false_type
|
||||||
|
template <typename T>
|
||||||
|
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||||
|
using std::disjunction;
|
||||||
|
#else
|
||||||
|
namespace detail {
|
||||||
|
/// Declares a C++14 polyfill for C++17 std::disjunction.
|
||||||
|
template <typename Args, typename = void_t<>>
|
||||||
|
struct disjunction_impl : std::common_type<std::true_type> {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct disjunction_impl<identity<Args...>,
|
||||||
|
void_t<std::enable_if_t<!bool(Args::value)>...>>
|
||||||
|
: std::common_type<std::false_type> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
using disjunction = typename detail::disjunction_impl<identity<Args...>>::type;
|
||||||
|
#endif // CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_HAS_CXX17_CONJUNCTION
|
||||||
|
using std::conjunction;
|
||||||
|
#else
|
||||||
|
namespace detail {
|
||||||
|
/// Declares a C++14 polyfill for C++17 std::conjunction.
|
||||||
|
template <typename Args, typename = void_t<>>
|
||||||
|
struct conjunction_impl : std::common_type<std::false_type> {};
|
||||||
|
template <typename... Args>
|
||||||
|
struct conjunction_impl<identity<Args...>,
|
||||||
|
void_t<std::enable_if_t<bool(Args::value)>...>>
|
||||||
|
: std::common_type<std::true_type> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
using conjunction = typename detail::conjunction_impl<identity<Args...>>::type;
|
||||||
|
#endif // CONTINUABLE_HAS_CXX17_CONJUNCTION
|
||||||
|
|
||||||
|
} // namespace traits
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cti
|
||||||
|
|
||||||
|
#endif // CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,23 +21,23 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_TRANSFORMS_FUTURE_HPP_INCLUDED
|
#ifndef CONTINUABLE_DETAIL_TRANSFORMS_HPP_INCLUDED
|
||||||
#define CONTINUABLE_DETAIL_TRANSFORMS_FUTURE_HPP_INCLUDED
|
#define CONTINUABLE_DETAIL_TRANSFORMS_HPP_INCLUDED
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
#include <continuable/detail/utility/util.hpp>
|
#include <continuable/detail/hints.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -77,7 +77,8 @@ template <typename Hint>
|
|||||||
class promise_callback;
|
class promise_callback;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
class promise_callback<identity<Args...>> : public future_trait<Args...> {
|
class promise_callback<hints::signature_hint_tag<Args...>>
|
||||||
|
: public future_trait<Args...> {
|
||||||
|
|
||||||
typename future_trait<Args...>::promise_t promise_;
|
typename future_trait<Args...>::promise_t promise_;
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the promise through the exception
|
/// Resolves the promise through the exception
|
||||||
void operator()(exception_arg_t, exception_t error) {
|
void operator()(types::dispatch_error_tag, types::error_type error) {
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||||
promise_.set_exception(error);
|
promise_.set_exception(error);
|
||||||
#else
|
#else
|
||||||
@ -103,7 +104,7 @@ public:
|
|||||||
// Can't forward a std::error_condition or custom error type
|
// Can't forward a std::error_condition or custom error type
|
||||||
// to a std::promise. Handle the error first in order
|
// to a std::promise. Handle the error first in order
|
||||||
// to prevent this trap!
|
// to prevent this trap!
|
||||||
CTI_DETAIL_TRAP();
|
util::trap();
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,10 +116,10 @@ public:
|
|||||||
|
|
||||||
/// Transforms the continuation to a future
|
/// Transforms the continuation to a future
|
||||||
template <typename Data, typename Annotation>
|
template <typename Data, typename Annotation>
|
||||||
auto to_future(continuable_base<Data, Annotation>&& continuable) {
|
auto as_future(continuable_base<Data, Annotation>&& continuable) {
|
||||||
// Create the promise which is able to supply the current arguments
|
// Create the promise which is able to supply the current arguments
|
||||||
constexpr auto const hint =
|
constexpr auto const hint =
|
||||||
base::annotation_of(identify<decltype(continuable)>{});
|
hints::hint_of(traits::identify<decltype(continuable)>{});
|
||||||
|
|
||||||
promise_callback<std::decay_t<decltype(hint)>> callback;
|
promise_callback<std::decay_t<decltype(hint)>> callback;
|
||||||
(void)hint;
|
(void)hint;
|
||||||
@ -135,4 +136,4 @@ auto to_future(continuable_base<Data, Annotation>&& continuable) {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_TRANSFORMS_FUTURE_HPP_INCLUDED
|
#endif // CONTINUABLE_DETAIL_TRANSFORMS_HPP_INCLUDED
|
||||||
@ -1,264 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_TRANSFORMS_WAIT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_TRANSFORMS_WAIT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <cassert>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
|
||||||
#include <continuable/detail/core/base.hpp>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
# include <exception>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace transforms {
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
class wait_transform_canceled_exception : public std::exception {
|
|
||||||
public:
|
|
||||||
wait_transform_canceled_exception() noexcept = default;
|
|
||||||
|
|
||||||
char const* what() const noexcept override {
|
|
||||||
return "cti::transforms::wait canceled due to cancellation of the "
|
|
||||||
"continuation";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
template <typename Hint>
|
|
||||||
struct sync_trait;
|
|
||||||
template <typename... Args>
|
|
||||||
struct sync_trait<identity<Args...>> {
|
|
||||||
using result_t = result<Args...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
using lock_t = std::unique_lock<std::mutex>;
|
|
||||||
using condition_variable_t = std::condition_variable;
|
|
||||||
|
|
||||||
template <typename Result>
|
|
||||||
struct unsafe_unlocker {
|
|
||||||
explicit unsafe_unlocker(std::atomic_bool* ready, condition_variable_t* cv,
|
|
||||||
std::mutex* mutex, Result* result)
|
|
||||||
: ready_(ready)
|
|
||||||
, cv_(cv)
|
|
||||||
, mutex_(mutex)
|
|
||||||
, result_(result) {}
|
|
||||||
|
|
||||||
unsafe_unlocker(unsafe_unlocker const&) = delete;
|
|
||||||
unsafe_unlocker(unsafe_unlocker&&) = default;
|
|
||||||
unsafe_unlocker& operator=(unsafe_unlocker const&) = delete;
|
|
||||||
unsafe_unlocker& operator=(unsafe_unlocker&&) = default;
|
|
||||||
|
|
||||||
~unsafe_unlocker() {
|
|
||||||
unlock(Result::empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void operator()(Args&&... args) {
|
|
||||||
unlock(Result::from(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock(Result&& result) {
|
|
||||||
if (!ownership_.is_acquired()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ownership_.release();
|
|
||||||
|
|
||||||
lock_t lock(*mutex_);
|
|
||||||
|
|
||||||
*result_ = std::move(result);
|
|
||||||
|
|
||||||
assert(!ready_->load(std::memory_order_acquire));
|
|
||||||
ready_->store(true, std::memory_order_release);
|
|
||||||
|
|
||||||
cv_->notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::atomic_bool* ready_;
|
|
||||||
condition_variable_t* cv_;
|
|
||||||
std::mutex* mutex_;
|
|
||||||
Result* result_;
|
|
||||||
util::ownership ownership_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Data, typename Annotation,
|
|
||||||
typename Result = typename sync_trait<Annotation>::result_t>
|
|
||||||
Result wait_relaxed(continuable_base<Data, Annotation>&& continuable) {
|
|
||||||
|
|
||||||
// Do an immediate unpack if the continuable is ready
|
|
||||||
if (continuable.is_ready()) {
|
|
||||||
return std::move(continuable).unpack();
|
|
||||||
}
|
|
||||||
|
|
||||||
condition_variable_t cv;
|
|
||||||
std::mutex cv_mutex;
|
|
||||||
|
|
||||||
std::atomic_bool ready{false};
|
|
||||||
Result sync_result;
|
|
||||||
|
|
||||||
std::move(continuable)
|
|
||||||
.next(unsafe_unlocker<Result>{
|
|
||||||
&ready,
|
|
||||||
&cv,
|
|
||||||
&cv_mutex,
|
|
||||||
&sync_result,
|
|
||||||
})
|
|
||||||
.done();
|
|
||||||
|
|
||||||
lock_t lock(cv_mutex);
|
|
||||||
if (!ready.load(std::memory_order_acquire)) {
|
|
||||||
cv.wait(lock, [&] {
|
|
||||||
return ready.load(std::memory_order_acquire);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return sync_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transforms the continuation to sync execution and unpacks the result the if
|
|
||||||
/// possible
|
|
||||||
template <typename Data, typename Annotation>
|
|
||||||
auto wait_and_unpack(continuable_base<Data, Annotation>&& continuable) {
|
|
||||||
|
|
||||||
auto sync_result = wait_relaxed(std::move(continuable));
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
if (sync_result.is_value()) {
|
|
||||||
return std::move(sync_result).get_value();
|
|
||||||
} else if (sync_result.is_exception()) {
|
|
||||||
if (sync_result.is_exception()) {
|
|
||||||
if (exception_t e = sync_result.get_exception()) {
|
|
||||||
std::rethrow_exception(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw wait_transform_canceled_exception();
|
|
||||||
#else
|
|
||||||
return sync_result;
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Result>
|
|
||||||
struct wait_frame {
|
|
||||||
std::mutex cv_mutex;
|
|
||||||
std::mutex rw_mutex;
|
|
||||||
condition_variable_t cv;
|
|
||||||
std::atomic_bool ready{false};
|
|
||||||
Result sync_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Result>
|
|
||||||
struct unlocker {
|
|
||||||
unlocker(unlocker const&) = delete;
|
|
||||||
unlocker(unlocker&&) = default;
|
|
||||||
unlocker& operator=(unlocker const&) = delete;
|
|
||||||
unlocker& operator=(unlocker&&) = default;
|
|
||||||
|
|
||||||
explicit unlocker(std::weak_ptr<wait_frame<Result>> frame)
|
|
||||||
: frame_(std::move(frame)) {}
|
|
||||||
|
|
||||||
~unlocker() {
|
|
||||||
unlock(Result::empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void operator()(Args&&... args) {
|
|
||||||
unlock(Result::from(std::forward<decltype(args)>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock(Result&& result) {
|
|
||||||
if (!ownership_.is_acquired()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ownership_.release();
|
|
||||||
|
|
||||||
if (auto locked = frame_.lock()) {
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> rw_lock(locked->rw_mutex);
|
|
||||||
assert(!locked->ready.load(std::memory_order_acquire));
|
|
||||||
locked->sync_result = std::move(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
locked->ready.store(true, std::memory_order_release);
|
|
||||||
locked->cv.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::weak_ptr<wait_frame<Result>> frame_;
|
|
||||||
util::ownership ownership_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Data, typename Annotation, typename Waiter,
|
|
||||||
typename Result = typename sync_trait<Annotation>::result_t>
|
|
||||||
Result wait_unsafe(continuable_base<Data, Annotation>&& continuable,
|
|
||||||
Waiter&& waiter) {
|
|
||||||
|
|
||||||
// Do an immediate unpack if the continuable is ready
|
|
||||||
if (continuable.is_ready()) {
|
|
||||||
return std::move(continuable).unpack();
|
|
||||||
}
|
|
||||||
|
|
||||||
using frame_t = wait_frame<Result>;
|
|
||||||
|
|
||||||
auto frame = std::make_shared<frame_t>();
|
|
||||||
|
|
||||||
std::move(continuable)
|
|
||||||
.next(unlocker<Result>{std::weak_ptr<frame_t>(frame)})
|
|
||||||
.done();
|
|
||||||
|
|
||||||
if (!frame->ready.load(std::memory_order_acquire)) {
|
|
||||||
lock_t lock(frame->cv_mutex);
|
|
||||||
std::forward<Waiter>(waiter)(frame->cv, lock, [&] {
|
|
||||||
return frame->ready.load(std::memory_order_acquire);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ([&] {
|
|
||||||
std::lock_guard<std::mutex> rw_lock(frame->rw_mutex);
|
|
||||||
Result cached = std::move(frame->sync_result);
|
|
||||||
return cached;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
} // namespace transforms
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_TRANSFORMS_WAIT_HPP_INCLUDED
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -39,8 +39,9 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/traversal/container-category.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/container-category.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -97,8 +98,10 @@ public:
|
|||||||
/// given iterator tuple.
|
/// given iterator tuple.
|
||||||
template <typename Frame, typename State>
|
template <typename Frame, typename State>
|
||||||
auto make_resume_traversal_callable(Frame&& frame, State&& state)
|
auto make_resume_traversal_callable(Frame&& frame, State&& state)
|
||||||
-> resume_traversal_callable<std::decay_t<Frame>, std::decay_t<State>> {
|
-> resume_traversal_callable<typename std::decay<Frame>::type,
|
||||||
return resume_traversal_callable<std::decay_t<Frame>, std::decay_t<State>>(
|
typename std::decay<State>::type> {
|
||||||
|
return resume_traversal_callable<typename std::decay<Frame>::type,
|
||||||
|
typename std::decay<State>::type>(
|
||||||
std::forward<Frame>(frame), std::forward<State>(state));
|
std::forward<Frame>(frame), std::forward<State>(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,8 +231,7 @@ struct static_async_range {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Position>
|
template <std::size_t Position>
|
||||||
constexpr auto relocate(std::integral_constant<std::size_t, Position>) const
|
constexpr auto relocate() const noexcept {
|
||||||
noexcept {
|
|
||||||
return static_async_range<Target, Position, End>{target_};
|
return static_async_range<Target, Position, End>{target_};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,9 +291,9 @@ struct dynamic_async_range {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using dynamic_async_range_of_t =
|
using dynamic_async_range_of_t = dynamic_async_range<
|
||||||
dynamic_async_range<std::decay_t<decltype(std::begin(std::declval<T>()))>,
|
typename std::decay<decltype(std::begin(std::declval<T>()))>::type,
|
||||||
std::decay_t<decltype(std::end(std::declval<T>()))>>;
|
typename std::decay<decltype(std::end(std::declval<T>()))>::type>;
|
||||||
|
|
||||||
/// Returns a dynamic range for the given type
|
/// Returns a dynamic range for the given type
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -335,8 +337,9 @@ public:
|
|||||||
auto hierarchy = std::tuple_cat(
|
auto hierarchy = std::tuple_cat(
|
||||||
std::make_tuple(std::forward<Parent>(parent)), hierarchy_);
|
std::make_tuple(std::forward<Parent>(parent)), hierarchy_);
|
||||||
|
|
||||||
return async_traversal_point<Frame, std::decay_t<Parent>, Hierarchy...>(
|
return async_traversal_point<Frame, typename std::decay<Parent>::type,
|
||||||
frame_, std::move(hierarchy), detached_);
|
Hierarchy...>(frame_, std::move(hierarchy),
|
||||||
|
detached_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forks the current traversal point and continues the child
|
/// Forks the current traversal point and continues the child
|
||||||
@ -402,7 +405,7 @@ public:
|
|||||||
/// Async traverse the current iterator
|
/// Async traverse the current iterator
|
||||||
template <typename Current>
|
template <typename Current>
|
||||||
void async_traverse_one(Current&& current) {
|
void async_traverse_one(Current&& current) {
|
||||||
using ElementType = std::decay_t<decltype(*current)>;
|
using ElementType = typename std::decay<decltype(*current)>::type;
|
||||||
return async_traverse_one_impl(container_category_of_t<ElementType>{},
|
return async_traverse_one_impl(container_category_of_t<ElementType>{},
|
||||||
std::forward<Current>(current));
|
std::forward<Current>(current));
|
||||||
}
|
}
|
||||||
@ -419,8 +422,8 @@ public:
|
|||||||
template <std::size_t... Sequence, typename Current>
|
template <std::size_t... Sequence, typename Current>
|
||||||
void async_traverse_static_async_range(
|
void async_traverse_static_async_range(
|
||||||
std::integer_sequence<std::size_t, Sequence...>, Current&& current) {
|
std::integer_sequence<std::size_t, Sequence...>, Current&& current) {
|
||||||
int dummy[] = {0, (async_traverse_one_checked(current.relocate(
|
int dummy[] = {0, ((void)async_traverse_one_checked(
|
||||||
std::integral_constant<std::size_t, Sequence>{})),
|
current.template relocate<Sequence>()),
|
||||||
0)...};
|
0)...};
|
||||||
(void)dummy;
|
(void)dummy;
|
||||||
(void)current;
|
(void)current;
|
||||||
@ -450,7 +453,8 @@ public:
|
|||||||
/// given frame and hierarchy
|
/// given frame and hierarchy
|
||||||
template <typename Frame, typename... Hierarchy>
|
template <typename Frame, typename... Hierarchy>
|
||||||
using traversal_point_of_t =
|
using traversal_point_of_t =
|
||||||
async_traversal_point<std::decay_t<Frame>, std::decay_t<Hierarchy>...>;
|
async_traversal_point<typename std::decay<Frame>::type,
|
||||||
|
typename std::decay<Hierarchy>::type...>;
|
||||||
|
|
||||||
/// A callable object which is capable of resuming an asynchronous
|
/// A callable object which is capable of resuming an asynchronous
|
||||||
/// pack traversal.
|
/// pack traversal.
|
||||||
@ -516,7 +520,7 @@ struct resume_state_callable {
|
|||||||
template <typename Frame, typename State>
|
template <typename Frame, typename State>
|
||||||
void resume_traversal_callable<Frame, State>::operator()() {
|
void resume_traversal_callable<Frame, State>::operator()() {
|
||||||
auto hierarchy = std::tuple_cat(std::make_tuple(frame_), state_);
|
auto hierarchy = std::tuple_cat(std::make_tuple(frame_), state_);
|
||||||
traits::unpack(resume_state_callable{}, std::move(hierarchy));
|
traits::unpack(std::move(hierarchy), resume_state_callable{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gives access to types related to the traversal frame
|
/// Gives access to types related to the traversal frame
|
||||||
@ -524,8 +528,8 @@ template <typename Visitor, typename... Args>
|
|||||||
struct async_traversal_types {
|
struct async_traversal_types {
|
||||||
/// Deduces to the async traversal frame type of the given
|
/// Deduces to the async traversal frame type of the given
|
||||||
/// traversal arguments and mapper
|
/// traversal arguments and mapper
|
||||||
using frame_t =
|
using frame_t = async_traversal_frame<typename std::decay<Visitor>::type,
|
||||||
async_traversal_frame<std::decay_t<Visitor>, std::decay_t<Args>...>;
|
typename std::decay<Args>::type...>;
|
||||||
|
|
||||||
/// The type of the demoted visitor type
|
/// The type of the demoted visitor type
|
||||||
using visitor_t = Visitor;
|
using visitor_t = Visitor;
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -37,8 +37,9 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <continuable/detail/traversal/container-category.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/container-category.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -169,7 +170,8 @@ struct flat_arraylizer {
|
|||||||
/// Deduces to the array type when the array is instantiated
|
/// Deduces to the array type when the array is instantiated
|
||||||
/// with the given arguments.
|
/// with the given arguments.
|
||||||
template <typename First, typename... Rest>
|
template <typename First, typename... Rest>
|
||||||
using array_type_of_t = Type<std::decay_t<First>, 1 + sizeof...(Rest)>;
|
using array_type_of_t =
|
||||||
|
Type<typename std::decay<First>::type, 1 + sizeof...(Rest)>;
|
||||||
|
|
||||||
// We overload with one argument here so Clang and GCC don't
|
// We overload with one argument here so Clang and GCC don't
|
||||||
// have any issues with overloading against zero arguments.
|
// have any issues with overloading against zero arguments.
|
||||||
@ -190,10 +192,10 @@ struct flat_arraylizer {
|
|||||||
template <typename C, typename... T>
|
template <typename C, typename... T>
|
||||||
constexpr auto apply_spread_impl(std::true_type, C&& callable, T&&... args)
|
constexpr auto apply_spread_impl(std::true_type, C&& callable, T&&... args)
|
||||||
-> decltype(
|
-> decltype(
|
||||||
traits::unpack(std::forward<C>(callable),
|
traits::unpack(std::tuple_cat(undecorate(std::forward<T>(args))...),
|
||||||
std::tuple_cat(undecorate(std::forward<T>(args))...))) {
|
std::forward<C>(callable))) {
|
||||||
return traits::unpack(std::forward<C>(callable),
|
return traits::unpack(std::tuple_cat(undecorate(std::forward<T>(args))...),
|
||||||
std::tuple_cat(undecorate(std::forward<T>(args))...));
|
std::forward<C>(callable));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use the linear instantiation for variadic packs which don't
|
/// Use the linear instantiation for variadic packs which don't
|
||||||
@ -406,8 +408,9 @@ using element_of_t = typename std::conditional<
|
|||||||
/// Removes all qualifier and references from the given type
|
/// Removes all qualifier and references from the given type
|
||||||
/// if the type is a l-value or r-value reference.
|
/// if the type is a l-value or r-value reference.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using dereferenced_of_t = typename std::conditional<std::is_reference<T>::value,
|
using dereferenced_of_t =
|
||||||
std::decay_t<T>, T>::type;
|
typename std::conditional<std::is_reference<T>::value,
|
||||||
|
typename std::decay<T>::type, T>::type;
|
||||||
|
|
||||||
/// Returns the type which is resulting if the mapping is applied to
|
/// Returns the type which is resulting if the mapping is applied to
|
||||||
/// an element in the container.
|
/// an element in the container.
|
||||||
@ -421,8 +424,8 @@ using mapped_type_from_t = dereferenced_of_t<spreading::unpacked_of_t<decltype(
|
|||||||
|
|
||||||
/// Deduces to a true_type if the mapping maps to zero elements.
|
/// Deduces to a true_type if the mapping maps to zero elements.
|
||||||
template <typename T, typename M>
|
template <typename T, typename M>
|
||||||
using is_empty_mapped = spreading::is_empty_spread<
|
using is_empty_mapped = spreading::is_empty_spread<typename std::decay<decltype(
|
||||||
std::decay_t<decltype(std::declval<M>()(std::declval<element_of_t<T>>()))>>;
|
std::declval<M>()(std::declval<element_of_t<T>>()))>::type>;
|
||||||
|
|
||||||
/// We are allowed to reuse the container if we map to the same
|
/// We are allowed to reuse the container if we map to the same
|
||||||
/// type we are accepting and when we have
|
/// type we are accepting and when we have
|
||||||
@ -470,9 +473,10 @@ template <typename M, typename T>
|
|||||||
auto remap_container(container_mapping_tag<false, false>, M&& mapper,
|
auto remap_container(container_mapping_tag<false, false>, M&& mapper,
|
||||||
T&& container)
|
T&& container)
|
||||||
-> decltype(rebind_container<mapped_type_from_t<T, M>>(container)) {
|
-> decltype(rebind_container<mapped_type_from_t<T, M>>(container)) {
|
||||||
static_assert(has_push_back<std::decay_t<T>, element_of_t<T>>::value,
|
static_assert(
|
||||||
"Can only remap containers that provide a push_back "
|
has_push_back<typename std::decay<T>::type, element_of_t<T>>::value,
|
||||||
"method!");
|
"Can only remap containers that provide a push_back "
|
||||||
|
"method!");
|
||||||
|
|
||||||
// Create the new container, which is capable of holding
|
// Create the new container, which is capable of holding
|
||||||
// the remappped types.
|
// the remappped types.
|
||||||
@ -500,7 +504,7 @@ auto remap_container(container_mapping_tag<false, false>, M&& mapper,
|
|||||||
/// type we accepted such as int -> int.
|
/// type we accepted such as int -> int.
|
||||||
template <typename M, typename T>
|
template <typename M, typename T>
|
||||||
auto remap_container(container_mapping_tag<false, true>, M&& mapper,
|
auto remap_container(container_mapping_tag<false, true>, M&& mapper,
|
||||||
T&& container) -> std::decay_t<T> {
|
T&& container) -> typename std::decay<T>::type {
|
||||||
for (auto&& val : container_accessor_of(std::forward<T>(container))) {
|
for (auto&& val : container_accessor_of(std::forward<T>(container))) {
|
||||||
val = spreading::unpack(
|
val = spreading::unpack(
|
||||||
std::forward<M>(mapper)(std::forward<decltype(val)>(val)));
|
std::forward<M>(mapper)(std::forward<decltype(val)>(val)));
|
||||||
@ -626,13 +630,14 @@ struct tuple_like_remapper<
|
|||||||
/// different types.
|
/// different types.
|
||||||
template <typename Strategy, typename T, typename M>
|
template <typename Strategy, typename T, typename M>
|
||||||
auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack(
|
auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack(
|
||||||
std::declval<
|
std::forward<T>(container),
|
||||||
tuple_like_remapper<Strategy, std::decay_t<M>, std::decay_t<T>>>(),
|
std::declval<tuple_like_remapper<Strategy, typename std::decay<M>::type,
|
||||||
std::forward<T>(container))) {
|
typename std::decay<T>::type>>())) {
|
||||||
return traits::unpack(
|
return traits::unpack(
|
||||||
tuple_like_remapper<Strategy, std::decay_t<M>, std::decay_t<T>>{
|
std::forward<T>(container),
|
||||||
std::forward<M>(mapper)},
|
tuple_like_remapper<Strategy, typename std::decay<M>::type,
|
||||||
std::forward<T>(container));
|
typename std::decay<T>::type>{
|
||||||
|
std::forward<M>(mapper)});
|
||||||
}
|
}
|
||||||
} // end namespace tuple_like_remapping
|
} // end namespace tuple_like_remapping
|
||||||
|
|
||||||
@ -641,7 +646,7 @@ auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack(
|
|||||||
template <typename Strategy>
|
template <typename Strategy>
|
||||||
struct mapping_strategy_base {
|
struct mapping_strategy_base {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto may_void(T&& element) const -> std::decay_t<T> {
|
auto may_void(T&& element) const -> typename std::decay<T>::type {
|
||||||
return std::forward<T>(element);
|
return std::forward<T>(element);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -799,19 +804,19 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
auto traverse(Strategy, T&& element)
|
auto traverse(Strategy, T&& element)
|
||||||
-> decltype(std::declval<mapping_helper>().match(
|
-> decltype(std::declval<mapping_helper>().match(
|
||||||
std::declval<container_category_of_t<std::decay_t<T>>>(),
|
std::declval<container_category_of_t<typename std::decay<T>::type>>(),
|
||||||
std::declval<T>()));
|
std::declval<T>()));
|
||||||
|
|
||||||
/// \copybrief traverse
|
/// \copybrief traverse
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto try_traverse(Strategy, T&& element)
|
auto try_traverse(Strategy, T&& element)
|
||||||
-> decltype(std::declval<mapping_helper>().try_match(
|
-> decltype(std::declval<mapping_helper>().try_match(
|
||||||
std::declval<container_category_of_t<std::decay_t<T>>>(),
|
std::declval<container_category_of_t<typename std::decay<T>::type>>(),
|
||||||
std::declval<T>())) {
|
std::declval<T>())) {
|
||||||
// We use tag dispatching here, to categorize the type T whether
|
// We use tag dispatching here, to categorize the type T whether
|
||||||
// it satisfies the container or tuple like requirements.
|
// it satisfies the container or tuple like requirements.
|
||||||
// Then we can choose the underlying implementation accordingly.
|
// Then we can choose the underlying implementation accordingly.
|
||||||
return try_match(container_category_of_t<std::decay_t<T>>{},
|
return try_match(container_category_of_t<typename std::decay<T>::type>{},
|
||||||
std::forward<T>(element));
|
std::forward<T>(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,7 +862,7 @@ public:
|
|||||||
/// Traverses the given pack with the given mapper and strategy
|
/// Traverses the given pack with the given mapper and strategy
|
||||||
template <typename Strategy, typename Mapper, typename... T>
|
template <typename Strategy, typename Mapper, typename... T>
|
||||||
decltype(auto) transform(Strategy strategy, Mapper&& mapper, T&&... pack) {
|
decltype(auto) transform(Strategy strategy, Mapper&& mapper, T&&... pack) {
|
||||||
mapping_helper<Strategy, std::decay_t<Mapper>> helper(
|
mapping_helper<Strategy, typename std::decay<Mapper>::type> helper(
|
||||||
std::forward<Mapper>(mapper));
|
std::forward<Mapper>(mapper));
|
||||||
return helper.init_traverse(strategy, std::forward<T>(pack)...);
|
return helper.init_traverse(strategy, std::forward<T>(pack)...);
|
||||||
}
|
}
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -31,10 +31,9 @@
|
|||||||
#ifndef CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
|
#ifndef CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
|
||||||
#define CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
|
#define CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
#include <continuable/detail/utility/identity.hpp>
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
@ -52,37 +51,32 @@ namespace detail {
|
|||||||
/// Contains types used globally across the library
|
/// Contains types used globally across the library
|
||||||
namespace types {
|
namespace types {
|
||||||
#ifdef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
#ifdef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||||
using exception_t = CONTINUABLE_WITH_CUSTOM_ERROR_TYPE;
|
using error_type = CONTINUABLE_WITH_CUSTOM_ERROR_TYPE;
|
||||||
#else // CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
#else // CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
/// Represents the exception type when exceptions are enabled
|
/// Represents the error type when exceptions are enabled
|
||||||
using exception_t = std::exception_ptr;
|
using error_type = std::exception_ptr;
|
||||||
#else // CONTINUABLE_WITH_NO_EXCEPTIONS
|
#else // CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
/// Represents the error type when exceptions are disabled
|
/// Represents the error type when exceptions are disabled
|
||||||
using exception_t = std::error_condition;
|
using error_type = std::error_condition;
|
||||||
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS
|
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||||
#endif // CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
#endif // CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||||
|
|
||||||
/// A tag which is used to execute the continuation inside the current thread
|
/// A tag which is used to execute the continuation inside the current thread
|
||||||
struct this_thread_executor_tag {};
|
struct this_thread_executor_tag {};
|
||||||
|
/// A tag which is used to continue with an error
|
||||||
|
struct dispatch_error_tag {};
|
||||||
|
|
||||||
/// Marks a given callable object as transformation
|
/// Marks a given callable object as transformation
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class plain_tag {
|
class transform : T {
|
||||||
T value_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename O, std::enable_if_t<std::is_constructible<
|
explicit transform(T callable) : T(std::move(callable)) {
|
||||||
T, std::decay_t<O>>::value>* = nullptr>
|
|
||||||
/* implicit */ plain_tag(O&& value) : value_(std::forward<O>(value)) {
|
|
||||||
}
|
|
||||||
explicit plain_tag(T value) : value_(std::move(value)) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
T&& consume() && {
|
using T::operator();
|
||||||
return std::move(value_);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace types
|
} // namespace types
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
\_,(_)| | | || ||_|(_||_)|(/_
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
https://github.com/Naios/continuable
|
||||||
v4.2.0
|
v3.0.0
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
of this software and associated documentation files(the "Software"), to deal
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
@ -32,184 +32,108 @@
|
|||||||
#define CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
#define CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
|
|
||||||
/// Hint for the compiler that this point should be unreachable
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE_INTRINSIC() __assume(false)
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE_INTRINSIC() __builtin_unreachable()
|
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_unreachable)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE_INTRINSIC() __builtin_unreachable()
|
|
||||||
#else
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE_INTRINSIC() abort()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Causes the application to exit abnormally
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_TRAP() __debugbreak()
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_TRAP() __builtin_trap()
|
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_trap)
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_TRAP() __builtin_trap()
|
|
||||||
#else
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_TRAP() *(volatile int*)0x11 = 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE() ::cti::detail::util::unreachable_debug()
|
|
||||||
#else
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
||||||
#define CTI_DETAIL_UNREACHABLE() CTI_DETAIL_UNREACHABLE_INTRINSIC()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
/// Utility namespace which provides useful meta-programming support
|
/// Utility namespace which provides useful meta-programming support
|
||||||
namespace util {
|
namespace util {
|
||||||
#ifndef NDEBUG
|
|
||||||
[[noreturn]] inline void unreachable_debug() {
|
|
||||||
CTI_DETAIL_TRAP();
|
|
||||||
std::abort();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Helper to trick compilers about that a parameter pack is used
|
/// Helper to trick compilers about that a parameter pack is used
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr void unused(T&&...) noexcept {
|
constexpr void unused(T&&...) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename T, std::size_t... I>
|
|
||||||
auto forward_except_last_impl(T&& tuple,
|
|
||||||
std::integer_sequence<std::size_t, I...>) {
|
|
||||||
(void)tuple;
|
|
||||||
return std::forward_as_tuple(std::get<I>(std::forward<T>(tuple))...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t Size>
|
|
||||||
constexpr auto make_decreased_index_sequence(
|
|
||||||
std::integral_constant<std::size_t, Size>) noexcept {
|
|
||||||
return std::make_index_sequence<Size - 1>();
|
|
||||||
}
|
|
||||||
inline void make_decreased_index_sequence(
|
|
||||||
std::integral_constant<std::size_t, 0U>) noexcept {
|
|
||||||
// This function is only instantiated on a compiler error and
|
|
||||||
// should not be included in valid code.
|
|
||||||
// See https://github.com/Naios/continuable/issues/21 for details.
|
|
||||||
CTI_DETAIL_UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Forwards every element in the tuple except the last one
|
/// Forwards every element in the tuple except the last one
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto forward_except_last(T&& sequenceable) {
|
auto forward_except_last(T&& sequenceable) {
|
||||||
static_assert(
|
constexpr auto const size = pack_size_of(traits::identify<T>()) - 1U;
|
||||||
std::tuple_size<std::decay_t<T>>::value > 0U,
|
constexpr auto const sequence = std::make_index_sequence<size>();
|
||||||
"Attempt to remove a parameter from an empty tuple like type! If you see "
|
|
||||||
"this your compiler could run into possible infinite recursion! Open a "
|
|
||||||
"ticket at https://github.com/Naios/continuable/issues with a small "
|
|
||||||
"reproducible example if your compiler doesn't stop!");
|
|
||||||
|
|
||||||
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
|
return traits::unpack(std::forward<T>(sequenceable),
|
||||||
constexpr auto sequence = make_decreased_index_sequence(
|
[](auto&&... args) {
|
||||||
std::integral_constant<std::size_t, size>{});
|
return std::forward_as_tuple(
|
||||||
|
std::forward<decltype(args)>(args)...);
|
||||||
return forward_except_last_impl(std::forward<T>(sequenceable), sequence);
|
},
|
||||||
|
sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Keep>
|
/// We are able to call the callable with the arguments given in the tuple
|
||||||
struct invocation_env {
|
template <typename T, typename... Args>
|
||||||
/// We are able to call the callable with the arguments given in the tuple
|
auto partial_invoke_impl(std::true_type, T&& callable,
|
||||||
template <typename T, typename... Args>
|
std::tuple<Args...> args) {
|
||||||
static auto partial_invoke_impl(std::true_type, T&& callable,
|
return traits::unpack(std::move(args), [&](auto&&... arg) {
|
||||||
std::tuple<Args...> args) {
|
return std::forward<T>(callable)(std::forward<decltype(arg)>(arg)...);
|
||||||
return traits::unpack(std::forward<T>(callable), std::move(args));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We were unable to call the callable with the arguments in the tuple.
|
/// We were unable to call the callable with the arguments in the tuple.
|
||||||
/// Remove the last argument from the tuple and try it again.
|
/// Remove the last argument from the tuple and try it again.
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static auto partial_invoke_impl(std::false_type, T&& callable,
|
auto partial_invoke_impl(std::false_type, T&& callable,
|
||||||
std::tuple<Args...> args) {
|
std::tuple<Args...> args) {
|
||||||
|
|
||||||
// If you are encountering this assertion you tried to attach a callback
|
// If you are encountering this assertion you tried to attach a callback
|
||||||
// which can't accept the arguments of the continuation.
|
// which can't accept the arguments of the continuation.
|
||||||
//
|
//
|
||||||
// ```cpp
|
// ```cpp
|
||||||
// continuable<int, int> c;
|
// continuable<int, int> c;
|
||||||
// std::move(c).then([](std::vector<int> v) { /*...*/ })
|
// std::move(c).then([](std::vector<int> v) { /*...*/ })
|
||||||
// ```
|
// ```
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof...(Args) > Keep,
|
sizeof...(Args) > 0,
|
||||||
"There is no way to call the given object with these arguments!");
|
"There is no way to call the given object with these arguments!");
|
||||||
|
|
||||||
// Remove the last argument from the tuple
|
// Remove the last argument from the tuple
|
||||||
auto next = forward_except_last(std::move(args));
|
auto next = forward_except_last(std::move(args));
|
||||||
|
|
||||||
// Test whether we are able to call the function with the given tuple
|
// Test whether we are able to call the function with the given tuple
|
||||||
constexpr std::integral_constant<
|
traits::is_invokable_from_tuple<decltype(callable), decltype(next)>
|
||||||
bool, traits::is_invocable_from_tuple<decltype(callable),
|
is_invokable;
|
||||||
decltype(next)>::value ||
|
|
||||||
(sizeof...(Args) <= Keep)>
|
|
||||||
is_callable;
|
|
||||||
|
|
||||||
return partial_invoke_impl(is_callable, std::forward<T>(callable),
|
return partial_invoke_impl(is_invokable, std::forward<T>(callable),
|
||||||
std::move(next));
|
std::move(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut - we can call the callable directly
|
/// Shortcut - we can call the callable directly
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static auto partial_invoke_impl_shortcut(std::true_type, T&& callable,
|
auto partial_invoke_impl_shortcut(std::true_type, T&& callable,
|
||||||
Args&&... args) {
|
Args&&... args) {
|
||||||
return std::forward<T>(callable)(std::forward<Args>(args)...);
|
return std::forward<T>(callable)(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Failed shortcut - we were unable to invoke the callable with the
|
/// Failed shortcut - we were unable to invoke the callable with the
|
||||||
/// original arguments.
|
/// original arguments.
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
static auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
|
auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable,
|
||||||
Args&&... args) {
|
Args&&... args) {
|
||||||
|
|
||||||
// Our shortcut failed, convert the arguments into a forwarding tuple
|
// Our shortcut failed, convert the arguments into a forwarding tuple
|
||||||
return partial_invoke_impl(
|
return partial_invoke_impl(
|
||||||
failed, std::forward<T>(callable),
|
failed, std::forward<T>(callable),
|
||||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/// Partially invokes the given callable with the given arguments.
|
/// Partially invokes the given callable with the given arguments.
|
||||||
///
|
///
|
||||||
/// \note This function will assert statically if there is no way to call the
|
/// \note This function will assert statically if there is no way to call the
|
||||||
/// given object with less arguments.
|
/// given object with less arguments.
|
||||||
template <std::size_t KeepArgs, typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
/*keep this inline*/ inline auto
|
/*keep this inline*/ inline auto partial_invoke(T&& callable, Args&&... args) {
|
||||||
partial_invoke(std::integral_constant<std::size_t, KeepArgs>, T&& callable,
|
|
||||||
Args&&... args) {
|
|
||||||
// Test whether we are able to call the function with the given arguments.
|
// Test whether we are able to call the function with the given arguments.
|
||||||
constexpr traits::is_invocable_from_tuple<decltype(callable),
|
traits::is_invokable_from_tuple<decltype(callable), std::tuple<Args...>>
|
||||||
std::tuple<Args...>>
|
is_invokable;
|
||||||
is_invocable;
|
|
||||||
|
|
||||||
// The implementation is done in a shortcut way so there are less
|
// The implementation is done in a shortcut way so there are less
|
||||||
// type instantiations needed to call the callable with its full signature.
|
// type instantiations needed to call the callable with its full signature.
|
||||||
using env = detail::invocation_env<KeepArgs>;
|
return detail::partial_invoke_impl_shortcut(
|
||||||
return env::partial_invoke_impl_shortcut(
|
is_invokable, std::forward<T>(callable), std::forward<Args>(args)...);
|
||||||
is_invocable, std::forward<T>(callable), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes the given callable object with the given arguments
|
/// Invokes the given callable object with the given arguments
|
||||||
@ -237,12 +161,6 @@ constexpr auto invoke(Type T::*member, Self&& self, Args&&... args) noexcept(
|
|||||||
return (std::forward<Self>(self)->*member)(std::forward<Args>(args)...);
|
return (std::forward<Self>(self)->*member)(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a constant view on the object
|
|
||||||
template <typename T>
|
|
||||||
constexpr std::add_const_t<T>& as_const(T& object) noexcept {
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class for making child classes non copyable
|
// Class for making child classes non copyable
|
||||||
struct non_copyable {
|
struct non_copyable {
|
||||||
constexpr non_copyable() = default;
|
constexpr non_copyable() = default;
|
||||||
@ -319,8 +237,39 @@ private:
|
|||||||
/// Is true when the automatic invocation on destruction is disabled
|
/// Is true when the automatic invocation on destruction is disabled
|
||||||
bool frozen_ : 1;
|
bool frozen_ : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Hint for the compiler that this point should be unreachable
|
||||||
|
[[noreturn]] inline void unreachable() {
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
__assume(false);
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
__builtin_unreachable();
|
||||||
|
#elif defined(__has_builtin) && __has_builtin(__builtin_unreachable)
|
||||||
|
__builtin_unreachable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Causes the application to exit abnormally because we are
|
||||||
|
/// in an invalid state.
|
||||||
|
[[noreturn]] inline void trap() {
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
__debugbreak();
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
__builtin_trap();
|
||||||
|
#elif defined(__has_builtin) && __has_builtin(__builtin_trap)
|
||||||
|
__builtin_trap();
|
||||||
|
#else
|
||||||
|
*(volatile int*)0 = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|
||||||
|
#ifdef CONTINUABLE_CONSTEXPR_IF
|
||||||
|
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
|
||||||
|
#else
|
||||||
|
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
|
||||||
|
#endif // CONTINUABLE_CONSTEXPR_IF
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
||||||
@ -1,54 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
/// A tagging type for wrapping other types
|
|
||||||
template <typename... T>
|
|
||||||
struct identity {};
|
|
||||||
|
|
||||||
template <typename>
|
|
||||||
struct is_identity : std::false_type {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct is_identity<identity<Args...>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
|
||||||
identity<std::decay_t<T>>>;
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_RESULT_TRAIT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_RESULT_TRAIT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/detail/core/annotation.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
#include <continuable/detail/utility/util.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
struct void_arg_t { };
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
struct result_trait;
|
|
||||||
template <>
|
|
||||||
struct result_trait<> {
|
|
||||||
using value_t = void;
|
|
||||||
using surrogate_t = void_arg_t;
|
|
||||||
|
|
||||||
static constexpr surrogate_t wrap() noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr void unwrap(surrogate_t) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
struct result_trait<T> {
|
|
||||||
using value_t = T;
|
|
||||||
using surrogate_t = value_t;
|
|
||||||
|
|
||||||
static surrogate_t wrap(T arg) {
|
|
||||||
return std::move(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
static decltype(auto) unwrap(R&& unwrap) {
|
|
||||||
return std::forward<R>(unwrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t I, typename Result>
|
|
||||||
static decltype(auto) get(Result&& result) {
|
|
||||||
return std::forward<Result>(result).get_value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename First, typename Second, typename... Rest>
|
|
||||||
struct result_trait<First, Second, Rest...> {
|
|
||||||
using value_t = std::tuple<First, Second, Rest...>;
|
|
||||||
using surrogate_t = value_t;
|
|
||||||
|
|
||||||
static surrogate_t wrap(First first, Second second, Rest... rest) {
|
|
||||||
return std::make_tuple(std::move(first), std::move(second),
|
|
||||||
std::move(rest)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
static decltype(auto) unwrap(R&& unwrap) {
|
|
||||||
return std::forward<R>(unwrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t I, typename Result>
|
|
||||||
static decltype(auto) get(Result&& result) {
|
|
||||||
return std::get<I>(std::forward<Result>(result).get_value());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_RESULT_TRAIT_HPP_INCLUDED
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_RESULT_VARIANT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_RESULT_VARIANT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace container {
|
|
||||||
enum class result_slot_t : std::uint8_t {
|
|
||||||
slot_empty,
|
|
||||||
slot_value,
|
|
||||||
slot_exception,
|
|
||||||
};
|
|
||||||
} // namespace container
|
|
||||||
|
|
||||||
struct init_empty_arg_t {};
|
|
||||||
struct init_result_arg_t {};
|
|
||||||
struct init_exception_arg_t {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class result_variant {
|
|
||||||
static constexpr bool is_nothrow_destructible = //
|
|
||||||
std::is_nothrow_destructible<T>::value &&
|
|
||||||
std::is_nothrow_destructible<exception_t>::value;
|
|
||||||
static constexpr bool is_nothrow_move_constructible = //
|
|
||||||
std::is_nothrow_move_constructible<T>::value &&
|
|
||||||
std::is_nothrow_move_constructible<exception_t>::value;
|
|
||||||
|
|
||||||
public:
|
|
||||||
result_variant() = default;
|
|
||||||
~result_variant() noexcept(is_nothrow_destructible) {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit result_variant(init_empty_arg_t) noexcept
|
|
||||||
: slot_(container::result_slot_t::slot_empty) {}
|
|
||||||
explicit result_variant(init_result_arg_t, T value) noexcept(
|
|
||||||
std::is_nothrow_destructible<T>::value&&
|
|
||||||
std::is_nothrow_move_constructible<T>::value)
|
|
||||||
: slot_(container::result_slot_t::slot_value) {
|
|
||||||
new (value_ptr()) T(std::move(value));
|
|
||||||
}
|
|
||||||
explicit result_variant(init_exception_arg_t, exception_t exception) noexcept(
|
|
||||||
std::is_nothrow_destructible<exception_t>::value&&
|
|
||||||
std::is_nothrow_move_constructible<exception_t>::value)
|
|
||||||
: slot_(container::result_slot_t::slot_exception) {
|
|
||||||
new (exception_ptr()) exception_t(std::move(exception));
|
|
||||||
}
|
|
||||||
|
|
||||||
result_variant(result_variant const&) = delete;
|
|
||||||
result_variant& operator=(result_variant const&) = delete;
|
|
||||||
|
|
||||||
result_variant(result_variant&& other) noexcept(
|
|
||||||
is_nothrow_destructible&& is_nothrow_move_constructible)
|
|
||||||
: slot_(other.slot_) {
|
|
||||||
|
|
||||||
switch (other.slot_) {
|
|
||||||
case container::result_slot_t::slot_value: {
|
|
||||||
new (value_ptr()) T(std::move(*other.value_ptr()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case container::result_slot_t::slot_exception: {
|
|
||||||
new (exception_ptr()) exception_t(std::move(*other.exception_ptr()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
other.destroy();
|
|
||||||
other.slot_ = container::result_slot_t::slot_empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
result_variant& operator=(result_variant&& other) noexcept(
|
|
||||||
is_nothrow_destructible&& is_nothrow_move_constructible) {
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
slot_ = other.slot_;
|
|
||||||
|
|
||||||
switch (other.slot_) {
|
|
||||||
case container::result_slot_t::slot_value: {
|
|
||||||
new (value_ptr()) T(std::move(*other.value_ptr()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case container::result_slot_t::slot_exception: {
|
|
||||||
new (exception_ptr()) exception_t(std::move(*other.exception_ptr()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
other.destroy();
|
|
||||||
other.slot_ = container::result_slot_t::slot_empty;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_empty() {
|
|
||||||
destroy();
|
|
||||||
slot_ = container::result_slot_t::slot_empty;
|
|
||||||
}
|
|
||||||
void set_value(T value) {
|
|
||||||
destroy();
|
|
||||||
new (value_ptr()) T(std::move(value));
|
|
||||||
slot_ = container::result_slot_t::slot_value;
|
|
||||||
}
|
|
||||||
void set_exception(exception_t exception) {
|
|
||||||
destroy();
|
|
||||||
new (exception_ptr()) exception_t(std::move(exception));
|
|
||||||
slot_ = container::result_slot_t::slot_exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
container::result_slot_t slot() const noexcept {
|
|
||||||
return slot_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_empty() const noexcept {
|
|
||||||
return slot_ == container::result_slot_t::slot_empty;
|
|
||||||
}
|
|
||||||
bool is_value() const noexcept {
|
|
||||||
return slot_ == container::result_slot_t::slot_value;
|
|
||||||
}
|
|
||||||
bool is_exception() const noexcept {
|
|
||||||
return slot_ == container::result_slot_t::slot_exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& get_value() noexcept {
|
|
||||||
assert(is_value());
|
|
||||||
return *reinterpret_cast<T*>(&storage_);
|
|
||||||
}
|
|
||||||
T const& get_value() const noexcept {
|
|
||||||
assert(is_value());
|
|
||||||
return *reinterpret_cast<T const*>(&storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception_t& get_exception() noexcept {
|
|
||||||
assert(is_exception());
|
|
||||||
return *reinterpret_cast<exception_t*>(&storage_);
|
|
||||||
}
|
|
||||||
exception_t const& get_exception() const noexcept {
|
|
||||||
assert(is_exception());
|
|
||||||
return *reinterpret_cast<exception_t const*>(&storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
constexpr T* value_ptr() noexcept {
|
|
||||||
return reinterpret_cast<T*>(&storage_);
|
|
||||||
}
|
|
||||||
constexpr exception_t* exception_ptr() noexcept {
|
|
||||||
return reinterpret_cast<exception_t*>(&storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy() noexcept(is_nothrow_destructible) {
|
|
||||||
switch (slot_) {
|
|
||||||
case container::result_slot_t::slot_value: {
|
|
||||||
value_ptr()->~T();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case container::result_slot_t::slot_exception: {
|
|
||||||
exception_ptr()->~exception_t();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
container::result_slot_t slot_{container::result_slot_t::slot_empty};
|
|
||||||
std::aligned_storage_t<
|
|
||||||
(sizeof(T) > sizeof(exception_t) ? sizeof(T) : sizeof(exception_t)),
|
|
||||||
(alignof(T) > alignof(exception_t) ? alignof(T) : alignof(exception_t))>
|
|
||||||
storage_;
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_RESULT_VARIANT_HPP_INCLUDED
|
|
||||||
@ -1,192 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/detail/features.hpp>
|
|
||||||
#include <continuable/detail/utility/identity.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
namespace detail {
|
|
||||||
namespace traits {
|
|
||||||
/// Removes all references and qualifiers from the given type T,
|
|
||||||
/// since std::decay has too much overhead through checking for
|
|
||||||
/// function pointers and arrays also.
|
|
||||||
template <typename T>
|
|
||||||
using unrefcv_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
struct index_of_impl;
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
struct index_of_impl<T, T, Args...> : std::integral_constant<std::size_t, 0U> {
|
|
||||||
};
|
|
||||||
template <typename T, typename U, typename... Args>
|
|
||||||
struct index_of_impl<T, U, Args...>
|
|
||||||
: std::integral_constant<std::size_t,
|
|
||||||
1 + index_of_impl<T, Args...>::value> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// Evaluates to the index of T in the given pack
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
using index_of_t = detail::index_of_impl<T, Args...>;
|
|
||||||
|
|
||||||
/// Creates a tuple in which r-values gets copied and
|
|
||||||
/// l-values keep their l-value.
|
|
||||||
template <typename... T>
|
|
||||||
auto make_flat_tuple(T&&... args) {
|
|
||||||
return std::tuple<T...>{std::forward<T>(args)...};
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_CXX17_VOID_T)
|
|
||||||
using std::void_t;
|
|
||||||
#else
|
|
||||||
namespace detail {
|
|
||||||
// Equivalent to C++17's std::void_t which targets a bug in GCC,
|
|
||||||
// that prevents correct SFINAE behavior.
|
|
||||||
// See http://stackoverflow.com/questions/35753920 for details.
|
|
||||||
template <typename...>
|
|
||||||
struct deduce_to_void : std::common_type<void> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// C++17 like void_t type
|
|
||||||
template <typename... T>
|
|
||||||
using void_t = typename detail::deduce_to_void<T...>::type;
|
|
||||||
#endif // CONTINUABLE_HAS_CXX17_VOID_T
|
|
||||||
|
|
||||||
namespace detail_unpack {
|
|
||||||
using std::get;
|
|
||||||
|
|
||||||
/// Calls the given unpacker with the content of the given sequenceable
|
|
||||||
template <typename U, typename F, std::size_t... I>
|
|
||||||
constexpr auto unpack_impl(U&& unpacker, F&& first_sequenceable,
|
|
||||||
std::integer_sequence<std::size_t, I...>)
|
|
||||||
-> decltype(std::forward<U>(unpacker)(
|
|
||||||
get<I>(std::forward<F>(first_sequenceable))...)) {
|
|
||||||
(void)first_sequenceable;
|
|
||||||
return std::forward<U>(unpacker)(
|
|
||||||
get<I>(std::forward<F>(first_sequenceable))...);
|
|
||||||
}
|
|
||||||
} // namespace detail_unpack
|
|
||||||
|
|
||||||
/// Calls the given callable object with the content of the given sequenceable
|
|
||||||
///
|
|
||||||
/// \note We can't use std::apply here since this implementation is SFINAE
|
|
||||||
/// aware and the std version not! This would lead to compilation errors.
|
|
||||||
template <typename Callable, typename TupleLike,
|
|
||||||
typename Sequence = std::make_index_sequence<
|
|
||||||
std::tuple_size<std::decay_t<TupleLike>>::value>>
|
|
||||||
constexpr auto unpack(Callable&& obj, TupleLike&& tuple_like)
|
|
||||||
-> decltype(detail_unpack::unpack_impl(std::forward<Callable>(obj),
|
|
||||||
std::forward<TupleLike>(tuple_like),
|
|
||||||
Sequence{})) {
|
|
||||||
|
|
||||||
return detail_unpack::unpack_impl(std::forward<Callable>(obj),
|
|
||||||
std::forward<TupleLike>(tuple_like),
|
|
||||||
Sequence{});
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename T, typename Args, typename = traits::void_t<>>
|
|
||||||
struct is_invokable_impl : std::common_type<std::false_type> {};
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
struct is_invokable_impl<
|
|
||||||
T, std::tuple<Args...>,
|
|
||||||
void_t<decltype(std::declval<T>()(std::declval<Args>()...))>>
|
|
||||||
: std::common_type<std::true_type> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// Deduces to a std::true_type if the given type is callable with the arguments
|
|
||||||
/// inside the given tuple.
|
|
||||||
/// The main reason for implementing it with the detection idiom instead of
|
|
||||||
/// hana like detection is that MSVC has issues with capturing raw template
|
|
||||||
/// arguments inside lambda closures.
|
|
||||||
///
|
|
||||||
/// ```cpp
|
|
||||||
/// traits::is_invocable<object, std::tuple<Args...>>
|
|
||||||
/// ```
|
|
||||||
template <typename T, typename Args>
|
|
||||||
using is_invocable_from_tuple =
|
|
||||||
typename detail::is_invokable_impl<T, Args>::type;
|
|
||||||
|
|
||||||
// Checks whether the given callable object is invocable with the given
|
|
||||||
// arguments. This doesn't take member functions into account!
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
using is_invocable = is_invocable_from_tuple<T, std::tuple<Args...>>;
|
|
||||||
|
|
||||||
/// Deduces to a std::false_type
|
|
||||||
template <typename T>
|
|
||||||
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
|
||||||
|
|
||||||
#ifdef CONTINUABLE_HAS_CXX17_DISJUNCTION
|
|
||||||
using std::disjunction;
|
|
||||||
#else
|
|
||||||
namespace detail {
|
|
||||||
/// Declares a C++14 polyfill for C++17 std::disjunction.
|
|
||||||
template <typename Args, typename = void_t<>>
|
|
||||||
struct disjunction_impl : std::common_type<std::true_type> {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct disjunction_impl<identity<Args...>,
|
|
||||||
void_t<std::enable_if_t<!bool(Args::value)>...>>
|
|
||||||
: std::common_type<std::false_type> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using disjunction = typename detail::disjunction_impl<identity<Args...>>::type;
|
|
||||||
#endif // CONTINUABLE_HAS_CXX17_DISJUNCTION
|
|
||||||
|
|
||||||
#ifdef CONTINUABLE_HAS_CXX17_CONJUNCTION
|
|
||||||
using std::conjunction;
|
|
||||||
#else
|
|
||||||
namespace detail {
|
|
||||||
/// Declares a C++14 polyfill for C++17 std::conjunction.
|
|
||||||
template <typename Args, typename = void_t<>>
|
|
||||||
struct conjunction_impl : std::common_type<std::false_type> {};
|
|
||||||
template <typename... Args>
|
|
||||||
struct conjunction_impl<identity<Args...>,
|
|
||||||
void_t<std::enable_if_t<bool(Args::value)>...>>
|
|
||||||
: std::common_type<std::true_type> {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using conjunction = typename detail::conjunction_impl<identity<Args...>>::type;
|
|
||||||
#endif // CONTINUABLE_HAS_CXX17_CONJUNCTION
|
|
||||||
|
|
||||||
} // namespace traits
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED
|
|
||||||
183
include/continuable/external/asio.hpp
vendored
183
include/continuable/external/asio.hpp
vendored
@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_EXTERNAL_ASIO_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_EXTERNAL_ASIO_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <continuable/continuable-base.hpp>
|
|
||||||
#include <continuable/detail/external/asio.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// The error code type used by your asio distribution
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
using asio_error_code_t = detail::asio::error_code_t;
|
|
||||||
|
|
||||||
/// The basic error code enum used by your asio distribution
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
using asio_basic_errors_t = detail::asio::basic_errors_t;
|
|
||||||
|
|
||||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
|
||||||
/// The system error type used by your asio distribution
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
using asio_system_error_t = detail::asio::system_error_t;
|
|
||||||
#endif // CONTINUABLE_HAS_EXCEPTIONS
|
|
||||||
|
|
||||||
/// Type used as an ASIO completion token to specify an asynchronous operation
|
|
||||||
/// that should return a continuable_base.
|
|
||||||
///
|
|
||||||
/// - Boost 1.70 or asio 1.13.0 is required for the async initiation
|
|
||||||
/// - Until boost 1.72 or asio 1.16.0 overhead through an additional type
|
|
||||||
/// erasure is added. It is recommended to update to those versions.
|
|
||||||
///
|
|
||||||
/// The special static variable use_continuable can be appended to any
|
|
||||||
/// (boost) asio function that accepts a callback to make it return a
|
|
||||||
/// continuable_base.
|
|
||||||
///
|
|
||||||
/// ```cpp
|
|
||||||
/// #include <continuable/continuable.hpp>
|
|
||||||
/// #include <continuable/external/asio.hpp>
|
|
||||||
/// #include <asio.hpp>
|
|
||||||
///
|
|
||||||
/// // ...
|
|
||||||
///
|
|
||||||
/// asio::tcp::resolver resolver(...);
|
|
||||||
/// resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
|
|
||||||
/// .then([](asio::udp::resolver::iterator iterator) {
|
|
||||||
/// // ...
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \tparam Mapper The token can be instantiated with a custom mapper
|
|
||||||
/// for asio error codes which makes it possible to ignore
|
|
||||||
/// errors or treat them as cancellation types.
|
|
||||||
/// The mapper has the following form:
|
|
||||||
/// ```
|
|
||||||
/// struct my_mapper {
|
|
||||||
/// constexpr my_mapper() noexcept {}
|
|
||||||
///
|
|
||||||
/// /// Returns true when the error_code_t is a type which represents
|
|
||||||
/// /// cancellation and
|
|
||||||
/// bool is_cancellation(error_code_t const& /*ec*/) const noexcept {
|
|
||||||
/// return false;
|
|
||||||
/// }
|
|
||||||
/// bool is_ignored(error_code_t const& /*ec*/) const noexcept {
|
|
||||||
/// return false;
|
|
||||||
/// }
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \attention `asio::error::basic_errors::operation_aborted` errors returned
|
|
||||||
/// by asio are automatically transformed into a default constructed
|
|
||||||
/// exception type which represents "operation canceled" by the
|
|
||||||
/// user or program. If you intend to retrieve the full
|
|
||||||
/// asio::error_code without remapping use the use_continuable_raw_t
|
|
||||||
/// completion token instead!
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename Mapper = detail::asio::map_default>
|
|
||||||
struct use_continuable_t : public Mapper {
|
|
||||||
using Mapper::Mapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \copydoc use_continuable_t
|
|
||||||
///
|
|
||||||
/// The raw async completion handler token does not remap the asio error
|
|
||||||
/// `asio::error::basic_errors::operation_aborted` to a default constructed
|
|
||||||
/// exception type.
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
using use_continuable_raw_t = use_continuable_t<detail::asio::map_none>;
|
|
||||||
|
|
||||||
/// Special value for instance of use_continuable_t which performs remapping
|
|
||||||
/// of asio error codes to align the cancellation behaviour with the library.
|
|
||||||
///
|
|
||||||
/// \copydetails use_continuable_t
|
|
||||||
constexpr use_continuable_t<> use_continuable{};
|
|
||||||
|
|
||||||
/// Special value for instance of use_continuable_raw_t which doesn't perform
|
|
||||||
/// remapping of asio error codes and rethrows the raw error code.
|
|
||||||
///
|
|
||||||
/// \copydetails use_continuable_raw_t
|
|
||||||
constexpr use_continuable_raw_t use_continuable_raw{};
|
|
||||||
|
|
||||||
/// Represents a special asio completion token which treats the given
|
|
||||||
/// asio basic error codes as success instead of failure.
|
|
||||||
///
|
|
||||||
/// `asio::error::basic_errors::operation_aborted` is mapped
|
|
||||||
/// as cancellation token.
|
|
||||||
///
|
|
||||||
/// \since 4.1.0
|
|
||||||
template <typename... Args>
|
|
||||||
auto use_continuable_ignoring(Args&&... args) noexcept {
|
|
||||||
return use_continuable_t<detail::asio::map_ignore<sizeof...(Args)>>{
|
|
||||||
{asio_basic_errors_t(std::forward<Args>(args))...}};
|
|
||||||
}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
CTI_DETAIL_ASIO_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
template <typename Signature, typename Matcher>
|
|
||||||
class async_result<cti::use_continuable_t<Matcher>, Signature> {
|
|
||||||
public:
|
|
||||||
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
|
|
||||||
using return_type = typename cti::detail::asio::initiate_make_continuable<
|
|
||||||
Signature>::erased_return_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Initiation, typename... Args>
|
|
||||||
static auto initiate(Initiation initiation,
|
|
||||||
cti::use_continuable_t<Matcher> token, Args... args) {
|
|
||||||
return cti::detail::asio::initiate_make_continuable<Signature>{}(
|
|
||||||
[initiation = std::move(initiation), token = std::move(token),
|
|
||||||
init_args = std::make_tuple(std::move(args)...)](
|
|
||||||
auto&& promise) mutable {
|
|
||||||
cti::detail::traits::unpack(
|
|
||||||
[initiation = std::move(initiation),
|
|
||||||
handler = cti::detail::asio::promise_resolver_handler(
|
|
||||||
std::forward<decltype(promise)>(promise), std::move(token))](
|
|
||||||
auto&&... args) mutable {
|
|
||||||
std::move(initiation)(std::move(handler),
|
|
||||||
std::forward<decltype(args)>(args)...);
|
|
||||||
},
|
|
||||||
std::move(init_args));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CTI_DETAIL_ASIO_NAMESPACE_END
|
|
||||||
|
|
||||||
#undef CTI_DETAIL_ASIO_NAMESPACE_BEGIN
|
|
||||||
#undef CTI_DETAIL_ASIO_NAMESPACE_END
|
|
||||||
#undef CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_EXTERNAL_ASIO_HPP_INCLUDED
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/detail/core/types.hpp>
|
|
||||||
#include <continuable/detail/operations/async.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \ingroup Operations
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// Wraps the given callable inside a continuable_base such that it is
|
|
||||||
/// invoked when the asynchronous result is requested to return the result.
|
|
||||||
///
|
|
||||||
/// The async function shall be seen as an equivalent to std::async.
|
|
||||||
///
|
|
||||||
/// The behaviour will be equal as when using make_ready_continuable together
|
|
||||||
/// with continuable_base::then, but async is implemented in
|
|
||||||
/// a more efficient way:
|
|
||||||
/// ```cpp
|
|
||||||
/// auto do_sth() {
|
|
||||||
/// return async([] {
|
|
||||||
/// do_sth_more();
|
|
||||||
/// return 0;
|
|
||||||
/// });
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \param callable The callable type which is invoked on request.
|
|
||||||
///
|
|
||||||
/// \param args The arguments which are passed to the callable upon invocation.
|
|
||||||
///
|
|
||||||
/// \returns A continuable_base which asynchronous result type will
|
|
||||||
/// be computed with the same rules as continuable_base::then .
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename Callable, typename... Args>
|
|
||||||
auto async(Callable&& callable, Args&&... args) {
|
|
||||||
return detail::operations::async(std::forward<Callable>(callable),
|
|
||||||
detail::types::this_thread_executor_tag{},
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps the given callable inside a continuable_base such that it is
|
|
||||||
/// invoked through the given executor when the asynchronous result
|
|
||||||
/// is requested to return the result.
|
|
||||||
///
|
|
||||||
/// The behaviour will be equal as when using make_ready_continuable together
|
|
||||||
/// with continuable_base::then and the given executor but async_on
|
|
||||||
/// is implemented in a more efficient way:
|
|
||||||
/// ```cpp
|
|
||||||
/// auto do_sth() {
|
|
||||||
/// auto executor = [](auto&& work) {
|
|
||||||
/// // Do something with the work here
|
|
||||||
/// std::forward<decltype(work)>(work);
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// return async_on([] {
|
|
||||||
/// do_sth_more();
|
|
||||||
/// return 0;
|
|
||||||
/// }, my_executor);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \param callable The callable type which is invoked on request.
|
|
||||||
///
|
|
||||||
/// \param executor The executor that is used to dispatch the given callable.
|
|
||||||
///
|
|
||||||
/// \param args The arguments which are passed to the callable upon invocation.
|
|
||||||
///
|
|
||||||
/// \returns A continuable_base which asynchronous result type will
|
|
||||||
/// be computed with the same rules as continuable_base::then .
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename Callable, typename Executor, typename... Args>
|
|
||||||
auto async_on(Callable&& callable, Executor&& executor, Args&&... args) {
|
|
||||||
return detail::operations::async(std::forward<Callable>(callable),
|
|
||||||
std::forward<Executor>(executor),
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_OPERATIONS_ASYNC_HPP_INCLUDED
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/continuable-primitives.hpp>
|
|
||||||
#include <continuable/continuable-result.hpp>
|
|
||||||
#include <continuable/detail/operations/loop.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \ingroup Operations
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// Can be used to create an asynchronous loop.
|
|
||||||
///
|
|
||||||
/// The callable will be called repeatedly until it returns a
|
|
||||||
/// cti::continuable_base which then resolves to a present cti::result.
|
|
||||||
///
|
|
||||||
/// For better readability cti::loop_result, cti::loop_break and
|
|
||||||
/// cti::loop_continue are provided which can be used as following:
|
|
||||||
/// ```cpp
|
|
||||||
/// auto while_answer_not_yes() {
|
|
||||||
/// return loop([] {
|
|
||||||
/// return ask_something().then([](std::string answer) -> loop_result<> {
|
|
||||||
/// if (answer == "yes") {
|
|
||||||
/// return loop_break();
|
|
||||||
/// } else {
|
|
||||||
/// return loop_continue();
|
|
||||||
/// }
|
|
||||||
/// });
|
|
||||||
/// });
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \param callable The callable type which must return a cti::continuable_base
|
|
||||||
/// which then resolves to a cti::result of arbitrary values.
|
|
||||||
///
|
|
||||||
/// \param args The arguments that are passed to the callable upon
|
|
||||||
/// each invocation.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename Callable, typename... Args>
|
|
||||||
auto loop(Callable&& callable, Args&&... args) {
|
|
||||||
return detail::operations::loop(std::forward<Callable>(callable),
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to indicate a specific result inside an asynchronous loop.
|
|
||||||
///
|
|
||||||
/// See cti::loop for details.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename... T>
|
|
||||||
using loop_result = plain_t<result<T...>>;
|
|
||||||
|
|
||||||
/// Can be used to create a loop_result which causes the loop to be
|
|
||||||
/// cancelled and resolved with the given arguments.
|
|
||||||
///
|
|
||||||
/// See cti::loop for details.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
template <typename... T>
|
|
||||||
auto loop_break(T&&... args) {
|
|
||||||
return make_plain(make_result(std::forward<T>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to create a loop_result which causes the loop to be repeated.
|
|
||||||
///
|
|
||||||
/// See cti::loop for details.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
inline auto loop_continue() noexcept {
|
|
||||||
return empty_result{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to create an asynchronous loop over a specific range.
|
|
||||||
///
|
|
||||||
/// The callable will be called repeatedly with each with begin increased
|
|
||||||
/// until end is reached.
|
|
||||||
///
|
|
||||||
/// ```cpp
|
|
||||||
/// auto iterate_some() {
|
|
||||||
/// // Iterate step from 0 to 9
|
|
||||||
/// return range_loop([] (int step) {
|
|
||||||
/// return do_something(i).then([] {
|
|
||||||
/// // You don't have to return a result here
|
|
||||||
/// });
|
|
||||||
/// }, 0, 10);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \param callable The callable type which must return a cti::continuable_base
|
|
||||||
/// which then resolves to a cti::result of arbitrary values.
|
|
||||||
///
|
|
||||||
/// \param begin The iterator to iterate over
|
|
||||||
///
|
|
||||||
/// \param end The iterator to iterate until
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename Callable, typename Iterator>
|
|
||||||
auto range_loop(Callable&& callable, Iterator begin, Iterator end) {
|
|
||||||
return detail::operations::loop( //
|
|
||||||
detail::operations::make_range_looper(std::forward<Callable>(callable),
|
|
||||||
begin, end));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_OPERATIONS_LOOP_HPP_INCLUDED
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
/~` _ _ _|_. _ _ |_ | _
|
|
||||||
\_,(_)| | | || ||_|(_||_)|(/_
|
|
||||||
|
|
||||||
https://github.com/Naios/continuable
|
|
||||||
v4.2.0
|
|
||||||
|
|
||||||
Copyright(c) 2015 - 2022 Denis Blank <denis.blank at outlook dot com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files(the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef CONTINUABLE_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
#define CONTINUABLE_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <continuable/detail/operations/split.hpp>
|
|
||||||
#include <continuable/detail/utility/traits.hpp>
|
|
||||||
|
|
||||||
namespace cti {
|
|
||||||
/// \ingroup Operations
|
|
||||||
/// \{
|
|
||||||
|
|
||||||
/// Splits the asynchronous control flow and merges multiple promises/callbacks
|
|
||||||
/// together, which take the same types of arguments, into one.
|
|
||||||
///
|
|
||||||
/// The invocation order of all promises is undefined.
|
|
||||||
///
|
|
||||||
/// The split function is the opposite of the connection functions
|
|
||||||
/// like `when_all` because is can merge multiple waiters together rather than
|
|
||||||
/// joining those.
|
|
||||||
///
|
|
||||||
/// The split function can be used to resolve multiple waiters when resolving
|
|
||||||
/// a single promise.
|
|
||||||
/// ```cpp
|
|
||||||
/// class my_class {
|
|
||||||
/// cti::promise<> promise_;
|
|
||||||
///
|
|
||||||
/// public:
|
|
||||||
/// cti::continuable<> wait_for_sth() {
|
|
||||||
/// return [this](auto&& promise) mutable {
|
|
||||||
/// // Make sure accessing promise_ is done in a thread safe way!
|
|
||||||
/// promise_ = cti::split(std::move(promise_),
|
|
||||||
/// std::forward<decltype(promise)>(promise));
|
|
||||||
/// };
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// void resolve_all() {
|
|
||||||
/// // Resolves all waiting promises
|
|
||||||
/// promise_.set_value();
|
|
||||||
/// }
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// \note The split function only works if all asynchronous arguments are
|
|
||||||
/// copyable. All asynchronous arguments and exceptions will be passed
|
|
||||||
/// to all split promises.
|
|
||||||
///
|
|
||||||
/// \param promises The promises to split the control flow into,
|
|
||||||
/// can be single promises or heterogeneous or homogeneous
|
|
||||||
/// containers of promises (see traverse_pack for a description
|
|
||||||
/// of supported nested arguments).
|
|
||||||
///
|
|
||||||
/// \returns A new promise with the same asynchronous result types as
|
|
||||||
/// the given promises.
|
|
||||||
///
|
|
||||||
/// \since 4.0.0
|
|
||||||
///
|
|
||||||
template <typename... Promises>
|
|
||||||
auto split(Promises&&... promises) {
|
|
||||||
return detail::operations::split_promise<
|
|
||||||
detail::traits::unrefcv_t<Promises>...>(
|
|
||||||
std::forward<Promises>(promises)...);
|
|
||||||
}
|
|
||||||
/// \}
|
|
||||||
} // namespace cti
|
|
||||||
|
|
||||||
#endif // CONTINUABLE_OPERATIONS_SPLIT_HPP_INCLUDED
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user