├── .clang-format ├── .github └── workflows │ └── libunifex-ci.yml ├── .gitignore ├── .install-libcxx.sh ├── .lldbinit ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── cmake ├── CMakeLists.txt.in ├── FindCoroutines.cmake ├── FindLibUring.cmake ├── FindMemoryResource.cmake ├── gtest.cmake ├── project-is-top-level.cmake ├── unifex_env.cmake ├── unifex_flags.cmake └── unifex_options.cmake ├── doc ├── api_reference.md ├── cancellation.md ├── concepts.md ├── customisation_points.md ├── debugging.md ├── overview.md └── type_erasure.md ├── examples ├── CMakeLists.txt ├── any_unique.cpp ├── async_auto_reset_event_count.cpp ├── async_mutex.cpp ├── async_trace.cpp ├── asynchronous_sleep.cpp ├── coroutine_stream_consumer.cpp ├── delayed_stream_cancellation.cpp ├── for_each_synchronous.cpp ├── for_each_via_thread_scheduler.cpp ├── for_each_via_trampoline.cpp ├── fp_delegation.cpp ├── get_scheduler.cpp ├── heap_allocate_operation.cpp ├── let.cpp ├── linux │ ├── http_server_io_uring_test.cpp │ ├── io_epoll_test.cpp │ └── io_uring_test.cpp ├── materialize.cpp ├── never_stream_cancellation.cpp ├── new_thread_context.cpp ├── p1897.cpp ├── produce_on_consume_via.cpp ├── reduce_synchronous.cpp ├── reduce_with_trampoline.cpp ├── schedule_with_subscheduler.cpp ├── static_thread_pool.cpp ├── stop_immediately.cpp ├── stream_cancellation.cpp ├── synchronous_sleep.cpp ├── type_erased_stream.cpp ├── when_all.cpp └── when_all_2.cpp ├── include └── unifex │ ├── adapt_stream.hpp │ ├── allocate.hpp │ ├── any_object.hpp │ ├── any_ref.hpp │ ├── any_scheduler.hpp │ ├── any_sender_of.hpp │ ├── any_unique.hpp │ ├── async_auto_reset_event.hpp │ ├── async_manual_reset_event.hpp │ ├── async_mutex.hpp │ ├── async_scope.hpp │ ├── async_trace.hpp │ ├── at_coroutine_exit.hpp │ ├── await_transform.hpp │ ├── bind_back.hpp │ ├── blocking.hpp │ ├── bulk_join.hpp │ ├── bulk_schedule.hpp │ ├── bulk_transform.hpp │ ├── cleanup_adapt_stream.hpp │ ├── config.hpp │ ├── connect_awaitable.hpp │ ├── continuations.hpp │ ├── coroutine.hpp │ ├── coroutine_concepts.hpp │ ├── create.hpp │ ├── defer.hpp │ ├── delay.hpp │ ├── dematerialize.hpp │ ├── detach_on_cancel.hpp │ ├── detail │ ├── any_heap_allocated_storage.hpp │ ├── atomic_intrusive_queue.hpp │ ├── concept_macros.hpp │ ├── debug_async_scope.hpp │ ├── epilogue.hpp │ ├── intrusive_heap.hpp │ ├── intrusive_list.hpp │ ├── intrusive_queue.hpp │ ├── intrusive_stack.hpp │ ├── prologue.hpp │ ├── type_erasure_builtins.hpp │ ├── unifex_fwd.hpp │ ├── vtable.hpp │ ├── with_abort_tag_invoke.hpp │ ├── with_forwarding_tag_invoke.hpp │ └── with_type_erased_tag_invoke.hpp │ ├── done_as_optional.hpp │ ├── exception.hpp │ ├── execution_policy.hpp │ ├── file_concepts.hpp │ ├── filesystem.hpp │ ├── filter_stream.hpp │ ├── finally.hpp │ ├── find_if.hpp │ ├── for_each.hpp │ ├── fused_stop_source.hpp │ ├── get_allocator.hpp │ ├── get_execution_policy.hpp │ ├── get_stop_token.hpp │ ├── indexed_for.hpp │ ├── inline_scheduler.hpp │ ├── inplace_stop_token.hpp │ ├── into_variant.hpp │ ├── invoke.hpp │ ├── io_concepts.hpp │ ├── just.hpp │ ├── just_done.hpp │ ├── just_error.hpp │ ├── just_from.hpp │ ├── just_void_or_done.hpp │ ├── let_done.hpp │ ├── let_error.hpp │ ├── let_value.hpp │ ├── let_value_with.hpp │ ├── let_value_with_stop_source.hpp │ ├── let_value_with_stop_token.hpp │ ├── linux │ ├── io_epoll_context.hpp │ ├── io_uring_context.hpp │ ├── mmap_region.hpp │ ├── monotonic_clock.hpp │ └── safe_file_descriptor.hpp │ ├── manual_event_loop.hpp │ ├── manual_lifetime.hpp │ ├── manual_lifetime_union.hpp │ ├── materialize.hpp │ ├── memory_resource.hpp │ ├── nest.hpp │ ├── never.hpp │ ├── new_thread_context.hpp │ ├── next_adapt_stream.hpp │ ├── null_receiver.hpp │ ├── on.hpp │ ├── on_stream.hpp │ ├── overload.hpp │ ├── pipe_concepts.hpp │ ├── range_stream.hpp │ ├── receiver_concepts.hpp │ ├── reduce_stream.hpp │ ├── repeat_effect_until.hpp │ ├── retry_when.hpp │ ├── schedule_with_subscheduler.hpp │ ├── scheduler_concepts.hpp │ ├── scope_guard.hpp │ ├── sender_concepts.hpp │ ├── sender_for.hpp │ ├── sequence.hpp │ ├── single.hpp │ ├── single_thread_context.hpp │ ├── socket_concepts.hpp │ ├── span.hpp │ ├── spawn_detached.hpp │ ├── spawn_future.hpp │ ├── spin_wait.hpp │ ├── static_thread_pool.hpp │ ├── std_concepts.hpp │ ├── stop_if_requested.hpp │ ├── stop_immediately.hpp │ ├── stop_on_request.hpp │ ├── stop_token_concepts.hpp │ ├── stop_when.hpp │ ├── stream_concepts.hpp │ ├── swap.hpp │ ├── sync_wait.hpp │ ├── tag_invoke.hpp │ ├── take_until.hpp │ ├── task.hpp │ ├── then.hpp │ ├── then_execute.hpp │ ├── this.hpp │ ├── thread_unsafe_event_loop.hpp │ ├── timed_single_thread_context.hpp │ ├── tracing │ ├── async_stack-inl.hpp │ ├── async_stack.hpp │ ├── get_async_stack_frame.hpp │ ├── get_return_address.hpp │ └── inject_async_stack.hpp │ ├── trampoline_scheduler.hpp │ ├── transform_stream.hpp │ ├── type_erased_stream.hpp │ ├── type_index.hpp │ ├── type_list.hpp │ ├── type_traits.hpp │ ├── typed_via.hpp │ ├── typed_via_stream.hpp │ ├── unhandled_done.hpp │ ├── unstoppable.hpp │ ├── unstoppable_token.hpp │ ├── upon_done.hpp │ ├── upon_error.hpp │ ├── v0 │ └── async_scope.hpp │ ├── v1 │ ├── async_scope.hpp │ └── debug_async_scope.hpp │ ├── v2 │ ├── async_scope.hpp │ └── debug_async_scope.hpp │ ├── variant_sender.hpp │ ├── via.hpp │ ├── via_stream.hpp │ ├── when_all.hpp │ ├── when_all_range.hpp │ ├── win32 │ ├── detail │ │ ├── ntapi.hpp │ │ ├── safe_handle.hpp │ │ └── types.hpp │ ├── filetime_clock.hpp │ ├── low_latency_iocp_context.hpp │ └── windows_thread_pool.hpp │ ├── with_allocator.hpp │ ├── with_query_value.hpp │ └── with_scheduler_affinity.hpp ├── source ├── CMakeLists.txt ├── async_auto_reset_event.cpp ├── async_manual_reset_event.cpp ├── async_mutex.cpp ├── async_stack.cpp ├── exception.cpp ├── inplace_stop_token.cpp ├── linux │ ├── io_epoll_context.cpp │ ├── io_uring_context.cpp │ ├── io_uring_syscall.cpp │ ├── io_uring_syscall.hpp │ ├── mmap_region.cpp │ ├── monotonic_clock.cpp │ └── safe_file_descriptor.cpp ├── manual_event_loop.cpp ├── static_thread_pool.cpp ├── task.cpp ├── thread_unsafe_event_loop.cpp ├── timed_single_thread_context.cpp ├── trampoline_scheduler.cpp ├── unifex.pc.in └── win32 │ ├── filetime_clock.cpp │ ├── low_latency_iocp_context.cpp │ ├── ntapi.cpp │ ├── safe_handle.cpp │ └── windows_thread_pool.cpp └── test ├── AsyncStackTest.cpp ├── CMakeLists.txt ├── allocate_test.cpp ├── any_object_test.cpp ├── any_scheduler_test.cpp ├── any_sender_of_test.cpp ├── any_unique_test.cpp ├── async_auto_reset_event_test.cpp ├── async_manual_reset_event_test.cpp ├── async_mutex_test.cpp ├── async_scope_test.cpp ├── async_scope_v0_test.cpp ├── async_scope_v2_test.cpp ├── at_coroutine_exit_test.cpp ├── awaitable_senders_test.cpp ├── bulk_schedule_test.cpp ├── cleanup_adapt_stream_test.cpp ├── create_test.cpp ├── debug_async_scope_test.cpp ├── delay_test.cpp ├── detach_on_cancel_test.cpp ├── filter_stream_test.cpp ├── finally_test.cpp ├── find_if_test.cpp ├── for_each_test.cpp ├── fused_stop_source_test.cpp ├── get_return_address_mock.hpp ├── get_scheduler_test.cpp ├── indexed_for_test.cpp ├── into_variant_test.cpp ├── invoke_test.cpp ├── io_uring_2_test.cpp ├── just_tests.cpp ├── just_void_or_done_test.cpp ├── let_done_test.cpp ├── let_error_test.cpp ├── let_value_test.cpp ├── let_value_with_stop_token_test.cpp ├── materialize_test.cpp ├── mock_receiver.hpp ├── nest_test.cpp ├── nothrow_task_test.cpp ├── on_stream_test.cpp ├── on_test.cpp ├── reduce_stream_test.cpp ├── repeat_effect_test.cpp ├── retry_when_test.cpp ├── schedule_with_subsceduler_test.cpp ├── single_test.cpp ├── spawn_detached_test.cpp ├── spawn_future_test.cpp ├── static_thread_pool_test.cpp ├── stop_on_request_test.cpp ├── stop_when_test.cpp ├── stoppable_receiver.hpp ├── tag_invoke_test.cpp ├── task_cancel_test.cpp ├── task_scheduler_affinity_test.cpp ├── task_test.cpp ├── task_void_test.cpp ├── then_test.cpp ├── type_erase_test.cpp ├── type_list_test.cpp ├── unstoppable_test.cpp ├── upon_done_test.cpp ├── upon_error_test.cpp ├── variant_sender_test.cpp ├── when_all_2_test.cpp ├── when_all_range_test.cpp ├── windows_iocp_context_test.cpp └── windows_threadpool_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ 3 | .vs/ 4 | /CMakeSettings.json 5 | /Folder.DotSettings.user 6 | /compile_commands.json 7 | /.cache 8 | -------------------------------------------------------------------------------- /.install-libcxx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Install a newer CMake version 4 | curl -sSL https://cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.sh -o install-cmake.sh 5 | chmod +x install-cmake.sh 6 | sudo ./install-cmake.sh --prefix=/usr/local --skip-license 7 | 8 | # Checkout LLVM sources 9 | git clone --depth=1 https://github.com/llvm-mirror/llvm.git llvm-source 10 | git clone --depth=1 https://github.com/llvm-mirror/libcxx.git llvm-source/projects/libcxx 11 | git clone --depth=1 https://github.com/llvm-mirror/libcxxabi.git llvm-source/projects/libcxxabi 12 | 13 | # Build and install libc++ (Use unstable ABI for better sanitizer coverage) 14 | mkdir llvm-build && cd llvm-build 15 | cmake -DCMAKE_C_COMPILER=clang-9 -DCMAKE_CXX_COMPILER=clang++-9 \ 16 | -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr \ 17 | ../llvm-source 18 | make cxx -j2 19 | sudo make install-cxxabi install-cxx 20 | cd ../ 21 | -------------------------------------------------------------------------------- /.lldbinit: -------------------------------------------------------------------------------- 1 | type summary add --summary-string "Open: ${var.opState_._M_i[0]%B} Ops: ${var.opState_._M_i[1-10]%u}" unifex::v2::_async_scope::async_scope 2 | type summary add --summary-string "${var.demangled}" unifex::detail::_debug_async_scope::op_base 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | cmake_minimum_required(VERSION 3.12) 7 | 8 | project(libunifex LANGUAGES CXX 9 | VERSION 0.1.0) 10 | 11 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 12 | 13 | include(project-is-top-level) 14 | include(unifex_options) 15 | include(unifex_env) 16 | include(unifex_flags) 17 | 18 | option(UNIFEX_USE_SYSTEM_GTEST "Use system GTest dependency" OFF) 19 | 20 | # The library target is defined in the source subdirectory 21 | add_subdirectory(source) 22 | 23 | # Don't build tests or examples if this project is not a top-level project 24 | # and only consumed via add_subdirectory in a git submodule fashion 25 | if (PROJECT_IS_TOP_LEVEL) 26 | # We enable testing in both cases, either if doing tests or building examples 27 | # Note, that examples are also registered as tests by subsequent calls to add_test() 28 | # You can run all tests or examples at once by using `ctest` or `ninja test` 29 | include(CTest) 30 | if(BUILD_TESTING OR UNIFEX_BUILD_EXAMPLES) 31 | # Examples do not use gtest 32 | if(UNIFEX_BUILD_EXAMPLES) 33 | add_subdirectory(examples) 34 | endif(UNIFEX_BUILD_EXAMPLES) 35 | # Tests do use gtest 36 | if(BUILD_TESTING) 37 | if(UNIFEX_USE_SYSTEM_GTEST) 38 | find_package(GTest CONFIG REQUIRED) 39 | # find_package(GMock REQUIRED) 40 | else() 41 | include(gtest) 42 | target_compile_features(gtest PUBLIC cxx_std_17) 43 | target_compile_features(gtest_main PUBLIC cxx_std_17) 44 | if (UNIFEX_CXX_COMPILER_CLANGCL) 45 | target_compile_options(gtest PRIVATE -Wno-error) 46 | target_compile_options(gtest_main PRIVATE -Wno-error) 47 | endif() 48 | endif() 49 | add_subdirectory(test) 50 | endif(BUILD_TESTING) 51 | endif(BUILD_TESTING OR UNIFEX_BUILD_EXAMPLES) 52 | endif(PROJECT_IS_TOP_LEVEL) 53 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to libunifex 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `master`. 9 | 2. If you've added code that should be tested, add tests. 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Facebook's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to libunifex, you agree that your contributions will be licensed 31 | under the LICENSE file in the root directory of this source tree. -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Facebook 2 | 3 | Licensed under the Apache License Version 2.0 with LLVM Exceptions 4 | (the "License"); you may not use this file except in compliance with 5 | the License. You may obtain a copy of the License at 6 | 7 | https://llvm.org/LICENSE.txt 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /cmake/CMakeLists.txt.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | cmake_minimum_required(VERSION 2.8.2) 7 | 8 | project(googletest-download NONE) 9 | 10 | include(ExternalProject) 11 | ExternalProject_Add(googletest 12 | GIT_REPOSITORY https://github.com/google/googletest.git 13 | GIT_TAG v1.14.0 14 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 15 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 16 | CONFIGURE_COMMAND "" 17 | BUILD_COMMAND "" 18 | INSTALL_COMMAND "" 19 | TEST_COMMAND "" 20 | ) 21 | -------------------------------------------------------------------------------- /cmake/FindLibUring.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. 2 | # 3 | # Licensed under the Apache License Version 2.0 with LLVM Exceptions 4 | # (the "License"); you may not use this file except in compliance with 5 | # the License. You may obtain a copy of the License at 6 | # 7 | # https://llvm.org/LICENSE.txt 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | find_path(LIBURING_INCLUDE_DIR NAMES liburing/io_uring.h linux/io_uring.h) 16 | mark_as_advanced(LIBURING_INCLUDE_DIR) 17 | 18 | #find_library(LIBURING_LIBRARY NAMES uring) 19 | #mark_as_advanced(LIBURING_LIBRARY) 20 | 21 | include(FindPackageHandleStandardArgs) 22 | FIND_PACKAGE_HANDLE_STANDARD_ARGS( 23 | LibUring 24 | REQUIRED_VARS LIBURING_INCLUDE_DIR) 25 | 26 | if(LibUring_FOUND) 27 | #set(LIBURING_LIBRARIES ${LIBURING_LIBRARY}) 28 | set(LIBURING_INCLUDE_DIRS ${LIBURING_INCLUDE_DIR}) 29 | endif() 30 | -------------------------------------------------------------------------------- /cmake/gtest.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | # Download and unpack googletest at configure time 7 | configure_file(cmake/CMakeLists.txt.in googletest-download/CMakeLists.txt) 8 | 9 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 10 | RESULT_VARIABLE result 11 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 12 | 13 | if(result) 14 | message(FATAL_ERROR "CMake step for googletest failed: ${result}") 15 | endif() 16 | 17 | execute_process(COMMAND ${CMAKE_COMMAND} --build . 18 | RESULT_VARIABLE result 19 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 20 | 21 | if(result) 22 | message(FATAL_ERROR "Build step for googletest failed: ${result}") 23 | endif() 24 | 25 | # Prevent overriding the parent project's compiler/linker 26 | # settings on Windows 27 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 28 | 29 | # Add googletest directly to our build. This defines 30 | # the gtest and gtest_main targets. 31 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src 32 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-build 33 | EXCLUDE_FROM_ALL) 34 | -------------------------------------------------------------------------------- /cmake/project-is-top-level.cmake: -------------------------------------------------------------------------------- 1 | # Taken from: https://github.com/friendlyanon/cmake-init-executable 2 | # This variable is set by project() in CMake 3.21+ 3 | string( 4 | COMPARE EQUAL 5 | "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" 6 | PROJECT_IS_TOP_LEVEL 7 | ) 8 | -------------------------------------------------------------------------------- /cmake/unifex_env.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | include(CheckCXXCompilerFlag) 7 | 8 | if("x${CMAKE_CXX_COMPILER_ID}" MATCHES "x.*Clang") 9 | if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") 10 | set (UNIFEX_CXX_COMPILER_CLANGCL TRUE) 11 | else() 12 | set (UNIFEX_CXX_COMPILER_CLANG TRUE) 13 | endif() 14 | elseif(CMAKE_COMPILER_IS_GNUCXX) 15 | set (UNIFEX_CXX_COMPILER_GCC TRUE) 16 | elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") 17 | set (UNIFEX_CXX_COMPILER_MSVC TRUE) 18 | else() 19 | message(WARNING "[unifex warning]: unknown compiler ${CMAKE_CXX_COMPILER_ID} !") 20 | endif() 21 | 22 | if (UNIFEX_CXX_COMPILER_MSVC) 23 | # warning level 3 and all warnings as errors 24 | add_compile_options(/W3 /WX) 25 | else() 26 | # lots of warnings and all warnings as errors 27 | add_compile_options(-Wall -Wextra -pedantic -Werror) 28 | endif() 29 | -------------------------------------------------------------------------------- /cmake/unifex_flags.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | include(CheckCXXCompilerFlag) 7 | include(CheckCXXSourceCompiles) 8 | include(CMakePushCheckState) 9 | include(CheckIncludeFile) 10 | include(CheckSymbolExists) 11 | 12 | if(DEFINED UNIFEX_NO_LIBURING) 13 | message(WARNING "[unifex warning]: forcing no_liburing=${UNIFEX_NO_LIBURING} !") 14 | elseif(DEFINED ENV{UNIFEX_NO_LIBURING}) 15 | message(WARNING "[unifex warning]: forcing no_liburing=$ENV{UNIFEX_NO_LIBURING} !") 16 | set(UNIFEX_NO_LIBURING $ENV{UNIFEX_NO_LIBURING}) 17 | set(LIBURING_INCLUDE_DIRS $ENV{UNIFEX_LIBURING_INCLUDE_DIRS}) 18 | set(LIBURING_LIBRARIES $ENV{UNIFEX_LIBURING_LIBRARIES}) 19 | else() 20 | # Probe for libUring support 21 | find_package(LibUring COMPONENTS) 22 | # Set some variables to be used by configure_file. 23 | if(LIBURING_FOUND) 24 | set(UNIFEX_NO_LIBURING FALSE) 25 | else() 26 | set(UNIFEX_NO_LIBURING TRUE) 27 | endif() 28 | endif() 29 | 30 | if(NOT UNIFEX_NO_LIBURING) 31 | set(UNIFEX_URING_INCLUDE_DIRS ${LIBURING_INCLUDE_DIRS}) 32 | set(UNIFEX_URING_LIBRARY ${LIBURING_LIBRARIES}) 33 | endif() 34 | 35 | if(DEFINED UNIFEX_NO_EPOLL) 36 | message(WARNING "[unifex warning]: forcing no_epoll=${UNIFEX_NO_EPOLL} !") 37 | elseif(DEFINED ENV{UNIFEX_NO_EPOLL}) 38 | message(WARNING "[unifex warning]: forcing no_epoll=$ENV{UNIFEX_NO_EPOLL} !") 39 | set(UNIFEX_NO_EPOLL $ENV{UNIFEX_NO_EPOLL}) 40 | else() 41 | # Probe for EPOLL support 42 | CHECK_SYMBOL_EXISTS(epoll_create "sys/epoll.h" UNIFEX_HAVE_SYS_EPOLL_CREATE) 43 | if(UNIFEX_HAVE_SYS_EPOLL_CREATE) 44 | set(UNIFEX_NO_EPOLL FALSE) 45 | else() 46 | set(UNIFEX_NO_EPOLL TRUE) 47 | endif() 48 | endif() 49 | -------------------------------------------------------------------------------- /cmake/unifex_options.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | include(CMakeDependentOption) 7 | 8 | option(UNIFEX_BUILD_EXAMPLES "Builds the libunifex examples." ON) 9 | -------------------------------------------------------------------------------- /doc/debugging.md: -------------------------------------------------------------------------------- 1 | # Async Stack Traces 2 | 3 | Unifex contains a prototype implementation of async stack-traces that 4 | allows you to traverse a chain/graph of async continuations. 5 | 6 | A stack-trace consists of a stack of `continuation_info` objects that 7 | describes the address of the "frame" and the type of the continuation 8 | as well as a mechanism to query what the next continuations in the chain are. 9 | 10 | This allows you to traverse from a leaf receiver back to the original task 11 | that launched it. If you are using structured concurrency and have represented 12 | your application as a structured set of tasks then this chain should progress 13 | all the way back to the root task of your application. 14 | 15 | Each receiver must customise the `visit_continuations()` CPO to be able to 16 | participate in the async stack-walk. Otherwise, the stack-walk will terminate 17 | when it reaches that receiver. 18 | 19 | Example: 20 | ```c++ 21 | template 22 | struct my_receiver { 23 | Receiver wrappedReceiver_; 24 | 25 | void set_value() && noexcept; 26 | void set_error(std::exception_ptr) && noexcept; 27 | void set_done() && noexcept; 28 | 29 | template 30 | friend void tag_invoke( 31 | tag_t, const my_receiver& r, Func&& func) { 32 | std::invoke(func, wrappedReceiver_); 33 | } 34 | }; 35 | ``` 36 | 37 | ## Capturing the current stack-trace 38 | 39 | There is a helper sender called `async_trace_sender` that you can use to 40 | get a dump of the async stack-trace at any point in a sender expression. 41 | It will produce a `std::vector` that contains a description 42 | of the async stack at this point. 43 | 44 | For example: Some helpers to dump an async trace. 45 | ```c++ 46 | auto dump_async_trace(std::string tag = {}) { 47 | return then( 48 | async_trace_sender{}, 49 | [tag = std::move(tag)](const std::vector& entries) { 50 | std::cout << "Async Trace (" << tag << "):\n"; 51 | for (auto& entry : entries) { 52 | std::cout << " " << entry.depth << " [-> " << entry.parentIndex 53 | << "]: " << entry.continuation.type().name() << " @ 0x"; 54 | std::cout.setf(std::ios::hex, std::ios::basefield); 55 | std::cout << entry.continuation.address(); 56 | std::cout.unsetf(std::ios::hex); 57 | std::cout << "\n"; 58 | } 59 | }); 60 | } 61 | 62 | template 63 | auto dump_async_trace_on_start(Sender&& sender, std::string tag = {}) { 64 | return unifex::sequence(dump_async_trace(std::move(tag)), (Sender &&) sender); 65 | } 66 | 67 | template 68 | auto dump_async_trace_on_completion(Sender&& sender, std::string tag = {}) { 69 | return unifex::finally( 70 | (Sender &&) sender, dump_async_trace(std::move(tag))); 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-present, Facebook, Inc. 2 | # 3 | # This source code is licensed under the license found in the 4 | # LICENSE.txt file in the root directory of this source tree. 5 | 6 | file(GLOB example-sources "*.cpp") 7 | foreach(file-path ${example-sources}) 8 | string( REPLACE ".cpp" "" file-path-without-ext ${file-path} ) 9 | get_filename_component(file-name ${file-path-without-ext} NAME) 10 | add_executable( ${file-name} ${file-path}) 11 | target_link_libraries(${file-name} PUBLIC unifex) 12 | add_test(NAME "example-${file-name}" COMMAND ${file-name}) 13 | endforeach() 14 | 15 | if (CMAKE_SYSTEM_NAME STREQUAL "Linux") 16 | file(GLOB linux-example-sources "linux/*.cpp") 17 | foreach(file-path ${linux-example-sources}) 18 | string( REPLACE ".cpp" "" file-path-without-ext ${file-path} ) 19 | get_filename_component(file-name ${file-path-without-ext} NAME) 20 | add_executable( ${file-name} ${file-path}) 21 | target_link_libraries(${file-name} PUBLIC unifex) 22 | add_test(NAME "example-${file-name}" COMMAND ${file-name}) 23 | endforeach() 24 | else() 25 | if (NOT UNIFEX_NO_EPOLL) 26 | file(GLOB epoll-example-sources "linux/*epoll_test.cpp") 27 | foreach(file-path ${epoll-example-sources}) 28 | string( REPLACE ".cpp" "" file-path-without-ext ${file-path} ) 29 | get_filename_component(file-name ${file-path-without-ext} NAME) 30 | add_executable( ${file-name} ${file-path}) 31 | target_link_libraries(${file-name} PUBLIC unifex) 32 | add_test(NAME "example-${file-name}" COMMAND ${file-name}) 33 | endforeach() 34 | endif() 35 | if (NOT UNIFEX_NO_LIBURING) 36 | file(GLOB liburing-example-sources "linux/*uring_test.cpp") 37 | foreach(file-path ${liburing-example-sources}) 38 | string( REPLACE ".cpp" "" file-path-without-ext ${file-path} ) 39 | get_filename_component(file-name ${file-path-without-ext} NAME) 40 | add_executable( ${file-name} ${file-path}) 41 | target_link_libraries(${file-name} PUBLIC unifex) 42 | add_test(NAME "example-${file-name}" COMMAND ${file-name}) 43 | endforeach() 44 | endif() 45 | endif() 46 | -------------------------------------------------------------------------------- /examples/async_auto_reset_event_count.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | using namespace unifex; 24 | 25 | int main() { 26 | async_auto_reset_event evt{true}; 27 | sync_wait(then( 28 | reduce_stream( 29 | evt.stream(), 30 | 0, 31 | [&evt](int count) { 32 | std::printf("got %i\n", count); 33 | if (count < 2) { 34 | evt.set(); 35 | } else { 36 | evt.set_done(); 37 | } 38 | return ++count; 39 | }), 40 | [](int result) { std::printf("result %d\n", result); })); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /examples/async_mutex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #if !UNIFEX_NO_COROUTINES 23 | 24 | # include 25 | # include 26 | # include 27 | # include 28 | 29 | # include 30 | 31 | using namespace unifex; 32 | 33 | int main() { 34 | async_mutex mutex; 35 | 36 | int sharedState = 0; 37 | 38 | auto makeTask = [&](manual_event_loop::scheduler scheduler) -> task { 39 | for (int i = 0; i < 100'000; ++i) { 40 | co_await mutex.async_lock(); 41 | co_await schedule(scheduler); 42 | ++sharedState; 43 | mutex.unlock(); 44 | } 45 | co_return 0; 46 | }; 47 | 48 | single_thread_context ctx1; 49 | single_thread_context ctx2; 50 | 51 | sync_wait( 52 | when_all(makeTask(ctx1.get_scheduler()), makeTask(ctx2.get_scheduler()))); 53 | 54 | if (sharedState != 200'000) { 55 | std::printf("error: incorrect result %i, expected 2000000\n", sharedState); 56 | return 1; 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | #else // UNIFEX_NO_COROUTINES 63 | 64 | # include 65 | 66 | int main() { 67 | // Very simple usage of async_mutex. 68 | 69 | unifex::async_mutex m; 70 | unifex::sync_wait(m.async_lock()); 71 | m.unlock(); 72 | 73 | return 0; 74 | } 75 | 76 | #endif // UNIFEX_NO_COROUTINES 77 | -------------------------------------------------------------------------------- /examples/asynchronous_sleep.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #if !UNIFEX_NO_COROUTINES 23 | # include 24 | #endif // UNIFEX_NO_COROUTINES 25 | #include 26 | 27 | using namespace unifex; 28 | using namespace std::chrono; 29 | using namespace std::chrono_literals; 30 | using namespace std; 31 | 32 | timed_single_thread_context timer; 33 | auto delay(milliseconds ms) { 34 | return schedule_after(timer.get_scheduler(), ms); 35 | } 36 | 37 | #if !UNIFEX_NO_COROUTINES 38 | unifex::task asyncMain() { 39 | co_await delay(1000ms); 40 | } 41 | #endif // UNIFEX_NO_COROUTINES 42 | 43 | int main() { 44 | auto start_time = steady_clock::now(); 45 | #if !UNIFEX_NO_COROUTINES 46 | sync_wait(asyncMain()); 47 | #endif // UNIFEX_NO_COROUTINES 48 | cout << "Total time is: " 49 | << duration_cast( 50 | steady_clock::now() - start_time) 51 | .count() 52 | << "ms\n"; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /examples/coroutine_stream_consumer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | 18 | #if !UNIFEX_NO_COROUTINES 19 | 20 | # include 21 | # include 22 | # include 23 | # include 24 | # include 25 | # include 26 | # include 27 | # include 28 | # include 29 | # include 30 | # include 31 | # include 32 | # include 33 | # include 34 | 35 | # include 36 | # include 37 | 38 | using namespace unifex; 39 | 40 | template 41 | auto done_as_void(Sender&& sender) { 42 | return let_done((Sender &&) sender, [] { return just(); }); 43 | } 44 | 45 | int main() { 46 | using namespace std::chrono; 47 | 48 | timed_single_thread_context context; 49 | 50 | auto makeTask = [&]() -> task { 51 | auto startTime = steady_clock::now(); 52 | 53 | auto s = take_until( 54 | stop_immediately( 55 | delay(range_stream{0, 100}, context.get_scheduler(), 50ms)), 56 | single(schedule_after(context.get_scheduler(), 500ms))); 57 | 58 | int sum = 0; 59 | while (auto value = co_await done_as_optional(next(s))) { 60 | auto ms = duration_cast(steady_clock::now() - startTime); 61 | std::printf("[%i ms] %i\n", (int)ms.count(), *value); 62 | std::fflush(stdout); 63 | 64 | sum += *value; 65 | } 66 | 67 | co_await done_as_void(cleanup(s)); 68 | 69 | auto ms = duration_cast(steady_clock::now() - startTime); 70 | std::printf("[%i ms] sum = %i\n", (int)ms.count(), sum); 71 | std::fflush(stdout); 72 | 73 | co_return sum; 74 | }; 75 | 76 | sync_wait(makeTask()); 77 | 78 | return 0; 79 | } 80 | 81 | #else // UNIFEX_NO_COROUTINES 82 | 83 | # include 84 | 85 | int main() { 86 | std::printf( 87 | "This test only supported for compilers that support coroutines\n"); 88 | return 0; 89 | } 90 | 91 | #endif // UNIFEX_NO_COROUTINES 92 | -------------------------------------------------------------------------------- /examples/delayed_stream_cancellation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | using namespace unifex; 32 | 33 | int main() { 34 | using namespace std::chrono; 35 | 36 | timed_single_thread_context context; 37 | 38 | auto startTime = steady_clock::now(); 39 | 40 | sync_wait(stop_when( 41 | for_each( 42 | delay(range_stream{0, 100}, context.get_scheduler(), 100ms), 43 | [startTime](int value) { 44 | auto ms = 45 | duration_cast(steady_clock::now() - startTime); 46 | std::printf("[%i ms] %i\n", (int)ms.count(), value); 47 | }), 48 | then(schedule_after(context.get_scheduler(), 500ms), [] { 49 | std::printf("cancelling\n"); 50 | }))); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /examples/for_each_synchronous.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | using namespace unifex; 25 | 26 | int main() { 27 | sync_wait(then( 28 | for_each( 29 | transform_stream( 30 | range_stream{0, 10}, [](int value) { return value * value; }), 31 | [](int value) { std::printf("got %i\n", value); }), 32 | []() { std::printf("done\n"); })); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /examples/for_each_via_thread_scheduler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | using namespace unifex; 27 | 28 | int main() { 29 | single_thread_context context; 30 | 31 | sync_wait(then( 32 | for_each( 33 | via_stream( 34 | context.get_scheduler(), 35 | transform_stream( 36 | range_stream{0, 10}, 37 | [](int value) { return value * value; })), 38 | [](int value) { std::printf("got %i\n", value); }), 39 | []() { std::printf("done\n"); })); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /examples/for_each_via_trampoline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | using namespace unifex; 27 | 28 | int main() { 29 | sync_wait(then( 30 | for_each( 31 | via_stream( 32 | trampoline_scheduler{}, 33 | transform_stream( 34 | range_stream{0, 10}, 35 | [](int value) { return value * value; })), 36 | [](int value) { std::printf("got %i\n", value); }), 37 | []() { std::printf("done"); })); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /examples/get_scheduler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | using namespace unifex; 29 | using namespace std::chrono_literals; 30 | 31 | int main() { 32 | timed_single_thread_context ctx; 33 | 34 | // Check that the schedule() operation can pick up the current 35 | // scheduler from the receiver which we inject by using 'with_query_value()'. 36 | sync_wait(with_query_value(schedule(), get_scheduler, ctx.get_scheduler())); 37 | 38 | // Check that the schedule_after(d) operation can pick up the current 39 | // scheduler from the receiver. 40 | sync_wait(with_query_value( 41 | schedule_after(200ms), get_scheduler, ctx.get_scheduler())); 42 | 43 | // Check that this can propagate through multiple levels of 44 | // composed operations. 45 | sync_wait(with_query_value( 46 | then( 47 | for_each( 48 | via_stream( 49 | current_scheduler, 50 | transform_stream( 51 | range_stream{0, 10}, 52 | [](int value) { return value * value; })), 53 | [](int value) { std::printf("got %i\n", value); }), 54 | []() { std::printf("done\n"); }), 55 | get_scheduler, 56 | ctx.get_scheduler())); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /examples/heap_allocate_operation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | using namespace unifex; 27 | 28 | int main() { 29 | single_thread_context threadContext; 30 | 31 | auto thread = threadContext.get_scheduler(); 32 | 33 | sync_wait(allocate( 34 | then(schedule(thread), [] { std::printf("hello libunifex!\n"); }))); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /examples/materialize.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | using namespace unifex; 28 | 29 | int main() { 30 | single_thread_context ctx; 31 | 32 | [[maybe_unused]] std::optional result = sync_wait(dematerialize( 33 | materialize(then(schedule(ctx.get_scheduler()), []() { return 42; })))); 34 | UNIFEX_ASSERT(result.value() == 42); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /examples/never_stream_cancellation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | using namespace std::literals::chrono_literals; 32 | using namespace unifex; 33 | 34 | int main() { 35 | timed_single_thread_context context; 36 | 37 | std::optional result = sync_wait(stop_when( 38 | for_each( 39 | never_stream{}, 40 | [](auto) { 41 | std::printf("got value"); 42 | std::fflush(stdout); 43 | }), 44 | then(schedule_after(context.get_scheduler(), 100ms), [] { 45 | std::printf("trigger completing, about to request stop\n"); 46 | }))); 47 | 48 | std::printf("completed with %s\n", result ? "unit" : "nullopt"); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /examples/produce_on_consume_via.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | using namespace unifex; 28 | 29 | int main() { 30 | single_thread_context context1; 31 | single_thread_context context2; 32 | 33 | sync_wait(then( 34 | for_each( 35 | via_stream( 36 | context1.get_scheduler(), 37 | on_stream( 38 | context2.get_scheduler(), 39 | transform_stream( 40 | range_stream{0, 10}, 41 | [](int value) { return value * value; }))), 42 | [](int value) { std::printf("got %i\n", value); }), 43 | []() { std::printf("done\n"); })); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /examples/reduce_synchronous.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | using namespace unifex; 25 | 26 | int main() { 27 | int finalResult; 28 | sync_wait(then( 29 | reduce_stream( 30 | transform_stream( 31 | range_stream{0, 10}, [](int value) { return value * value; }), 32 | 0, 33 | [](int state, int value) { return state + value; }), 34 | [&](int result) { finalResult = result; })); 35 | 36 | std::printf("result = %i\n", finalResult); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /examples/reduce_with_trampoline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | using namespace unifex; 27 | 28 | // This test uses the trampoline_scheduler to avoid stack-overflow due to very 29 | // deep recursion from a reduce over a synchronous stream. 30 | 31 | int main() { 32 | sync_wait(then( 33 | reduce_stream( 34 | via_stream( 35 | trampoline_scheduler{}, 36 | transform_stream( 37 | range_stream{0, 100'000}, 38 | [](unsigned value) { return value * value; })), 39 | 0, 40 | [](unsigned state, unsigned value) { return state + 10 * value; }), 41 | [&](unsigned result) { std::printf("result: %i\n", result); })); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/schedule_with_subscheduler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace unifex; 22 | 23 | int main() { 24 | timed_single_thread_context context; 25 | auto schedr = context.get_scheduler(); 26 | 27 | std::optional result = sync_wait( 28 | then(schedule_with_subscheduler(schedr), [&](auto subScheduler) noexcept { 29 | return subScheduler == schedr; 30 | })); 31 | 32 | if (result.has_value() && result.value()) { 33 | // Success 34 | return 0; 35 | } 36 | 37 | return 1; 38 | } 39 | -------------------------------------------------------------------------------- /examples/static_thread_pool.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | using namespace unifex; 26 | 27 | template 28 | auto run_on(Scheduler&& s, F&& func) { 29 | return then(schedule((Scheduler &&) s), (F &&) func); 30 | } 31 | 32 | int main() { 33 | static_thread_pool tpContext; 34 | auto tp = tpContext.get_scheduler(); 35 | std::atomic x = 0; 36 | 37 | sync_wait(when_all( 38 | run_on( 39 | tp, 40 | [&] { 41 | ++x; 42 | std::printf("task 1\n"); 43 | }), 44 | run_on( 45 | tp, 46 | [&] { 47 | ++x; 48 | std::printf("task 2\n"); 49 | }), 50 | run_on(tp, [&] { 51 | ++x; 52 | std::printf("task 3\n"); 53 | }))); 54 | 55 | UNIFEX_ASSERT(x == 3); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /examples/stop_immediately.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | using namespace unifex; 30 | using namespace std::chrono; 31 | 32 | int main() { 33 | thread_unsafe_event_loop eventLoop; 34 | 35 | std::printf("starting\n"); 36 | 37 | auto startTime = steady_clock::now(); 38 | 39 | [[maybe_unused]] std::optional result = eventLoop.sync_wait(for_each( 40 | take_until( 41 | stop_immediately( 42 | delay(range_stream{0, 100}, eventLoop.get_scheduler(), 50ms)), 43 | single(schedule_after(eventLoop.get_scheduler(), 500ms))), 44 | [startTime](int value) { 45 | auto ms = duration_cast(steady_clock::now() - startTime); 46 | std::printf("[%i ms] %i\n", (int)ms.count(), value); 47 | })); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /examples/stream_cancellation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace unifex; 31 | using namespace std::literals::chrono_literals; 32 | 33 | int main() { 34 | timed_single_thread_context context; 35 | 36 | using namespace std::chrono; 37 | 38 | auto startTime = steady_clock::now(); 39 | 40 | auto op = on_stream(current_scheduler, range_stream{0, 20}) | 41 | for_each([](int value) { 42 | // Simulate some work 43 | std::printf("processing %i\n", value); 44 | std::this_thread::sleep_for(10ms); 45 | }) | 46 | stop_when(schedule_after(100ms)); 47 | sync_wait(on(context.get_scheduler(), std::move(op))); 48 | 49 | auto endTime = steady_clock::now(); 50 | 51 | std::printf( 52 | "took %i ms\n", 53 | (int)duration_cast(endTime - startTime).count()); 54 | } 55 | -------------------------------------------------------------------------------- /examples/synchronous_sleep.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace unifex; 26 | using namespace std::chrono; 27 | using namespace std::chrono_literals; 28 | using namespace std; 29 | 30 | auto delay(milliseconds ms) { 31 | return schedule_after(current_scheduler, ms); 32 | } 33 | 34 | timed_single_thread_context timer; 35 | void sleep() { 36 | on(timer.get_scheduler(), delay(1000ms)) | sync_wait(); 37 | } 38 | 39 | int main() { 40 | auto start_time = steady_clock::now(); 41 | sleep(); 42 | cout << "Total time is: " 43 | << duration_cast( 44 | steady_clock::now() - start_time) 45 | .count() 46 | << "ms\n"; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples/type_erased_stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | using namespace unifex; 29 | 30 | int main() { 31 | single_thread_context context1; 32 | single_thread_context context2; 33 | 34 | sync_wait(then( 35 | for_each( 36 | type_erase(via_stream( 37 | context1.get_scheduler(), 38 | on_stream( 39 | context2.get_scheduler(), 40 | transform_stream( 41 | range_stream{0, 10}, 42 | [](int value) { return value * value; })))), 43 | [](int value) { std::printf("got %i\n", value); }), 44 | []() { std::printf("done\n"); })); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /examples/when_all.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | using namespace unifex; 26 | using namespace std::chrono; 27 | using namespace std::chrono_literals; 28 | 29 | int main() { 30 | timed_single_thread_context context; 31 | auto scheduler = context.get_scheduler(); 32 | 33 | auto startTime = steady_clock::now(); 34 | 35 | sync_wait(then( 36 | when_all( 37 | then( 38 | schedule_after(scheduler, 100ms), 39 | [=]() { 40 | auto time = steady_clock::now() - startTime; 41 | auto timeMs = duration_cast(time).count(); 42 | std::cout << "part1 finished - [" << timeMs << "]\n"; 43 | return time; 44 | }), 45 | then( 46 | schedule_after(scheduler, 200ms), 47 | [=]() { 48 | auto time = steady_clock::now() - startTime; 49 | auto timeMs = duration_cast(time).count(); 50 | std::cout << "part2 finished - [" << timeMs << "]\n"; 51 | return time; 52 | })), 53 | [](auto&& a, auto&& b) { 54 | std::cout 55 | << "when_all finished - [" 56 | << duration_cast(std::get<0>(std::get<0>(a))).count() 57 | << ", " 58 | << duration_cast(std::get<0>(std::get<0>(b))).count() 59 | << "]\n"; 60 | })); 61 | 62 | std::cout << "all done\n"; 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /include/unifex/async_scope.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | -------------------------------------------------------------------------------- /include/unifex/cleanup_adapt_stream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace unifex { 27 | namespace _cleanup_adapt { 28 | template 29 | struct _stream final { 30 | struct type; 31 | }; 32 | template 33 | using stream = 34 | typename _stream, std::decay_t>::type; 35 | 36 | template 37 | struct _stream::type final { 38 | UNIFEX_NO_UNIQUE_ADDRESS Stream innerStream_; 39 | UNIFEX_NO_UNIQUE_ADDRESS AdaptFunc adapter_; 40 | 41 | friend auto 42 | tag_invoke(tag_t, type& s) noexcept(noexcept(next(s.innerStream_))) 43 | -> next_sender_t { 44 | return next(s.innerStream_); 45 | } 46 | 47 | friend auto tag_invoke(tag_t, type& s) noexcept( 48 | noexcept(std::invoke(s.adapter_, cleanup(s.innerStream_)))) 49 | -> std::invoke_result_t> { 50 | return std::invoke(s.adapter_, cleanup(s.innerStream_)); 51 | } 52 | }; 53 | } // namespace _cleanup_adapt 54 | 55 | namespace _cleanup_adapt_cpo { 56 | inline constexpr struct _fn final { 57 | template 58 | constexpr auto operator()(Stream&& stream, AdaptFunc&& adapt) const noexcept( 59 | std::is_nothrow_constructible_v, Stream>&& 60 | std::is_nothrow_constructible_v, AdaptFunc>) { 61 | return _cleanup_adapt::stream{ 62 | (Stream&&)stream, (AdaptFunc&&)adapt}; 63 | } 64 | } cleanup_adapt_stream{}; 65 | } // namespace _cleanup_adapt_cpo 66 | 67 | using _cleanup_adapt_cpo::cleanup_adapt_stream; 68 | 69 | } // namespace unifex 70 | 71 | #include 72 | -------------------------------------------------------------------------------- /include/unifex/coroutine.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | #if !UNIFEX_NO_COROUTINES 21 | # include UNIFEX_COROUTINES_HEADER 22 | 23 | namespace unifex { 24 | namespace coro = UNIFEX_COROUTINES_NAMESPACE; 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /include/unifex/defer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | namespace unifex { 25 | namespace _defer { 26 | inline const struct _fn { 27 | template(typename Callable)( 28 | requires std::is_invocable_v AND 29 | sender>) constexpr auto 30 | operator()(Callable&& invocable) const { 31 | return let_value(just(), (Callable &&) invocable); 32 | } 33 | } defer{}; 34 | } // namespace _defer 35 | using _defer::defer; 36 | } // namespace unifex 37 | 38 | #include 39 | -------------------------------------------------------------------------------- /include/unifex/delay.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace unifex { 29 | namespace _delay { 30 | inline const struct _fn { 31 | template 32 | auto operator()( 33 | Stream&& stream, Scheduler&& scheduler, Duration&& duration) const { 34 | return adapt_stream( 35 | (Stream &&) stream, 36 | [scheduler = (Scheduler &&) scheduler, 37 | duration = (Duration &&) duration](auto&& sender) { 38 | return finally( 39 | static_cast(sender), 40 | schedule_after(scheduler, duration)); 41 | }); 42 | } 43 | template 44 | constexpr auto operator()(Scheduler&& scheduler, Duration&& duration) const 45 | noexcept( 46 | std::is_nothrow_invocable_v, _fn, Scheduler, Duration>) 47 | -> bind_back_result_t<_fn, Scheduler, Duration> { 48 | return bind_back(*this, (Scheduler &&) scheduler, (Duration &&) duration); 49 | } 50 | } delay{}; 51 | } // namespace _delay 52 | using _delay::delay; 53 | } // namespace unifex 54 | 55 | #include 56 | -------------------------------------------------------------------------------- /include/unifex/detail/epilogue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // No include guard or pragma once. This file is intended to be included 18 | // multiple times. 19 | 20 | #ifndef UNIFEX_PROLOGUE_HPP 21 | # error Epilogue included but prologue has not 22 | #endif 23 | #undef UNIFEX_PROLOGUE_HPP 24 | 25 | #undef template 26 | #undef AND 27 | -------------------------------------------------------------------------------- /include/unifex/detail/intrusive_stack.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | namespace unifex { 21 | 22 | template 23 | class intrusive_stack { 24 | public: 25 | intrusive_stack() : head_(nullptr) {} 26 | 27 | intrusive_stack(intrusive_stack&& other) noexcept 28 | : head_(std::exchange(other.head_, nullptr)) {} 29 | 30 | intrusive_stack(const intrusive_stack&) = delete; 31 | intrusive_stack& operator=(const intrusive_stack&) = delete; 32 | intrusive_stack& operator=(intrusive_stack&&) = delete; 33 | 34 | ~intrusive_stack() { UNIFEX_ASSERT(empty()); } 35 | 36 | // Adopt an existing linked-list as a stack. 37 | static intrusive_stack adopt(T* head) noexcept { 38 | intrusive_stack stack; 39 | stack.head_ = head; 40 | return stack; 41 | } 42 | 43 | T* release() noexcept { return std::exchange(head_, nullptr); } 44 | 45 | [[nodiscard]] bool empty() const noexcept { return head_ == nullptr; } 46 | 47 | void push_front(T* item) noexcept { 48 | item->*Next = head_; 49 | head_ = item; 50 | } 51 | 52 | [[nodiscard]] T* pop_front() noexcept { 53 | UNIFEX_ASSERT(!empty()); 54 | T* item = head_; 55 | head_ = item->*Next; 56 | return item; 57 | } 58 | 59 | private: 60 | T* head_; 61 | }; 62 | 63 | } // namespace unifex 64 | -------------------------------------------------------------------------------- /include/unifex/detail/prologue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // No include guard or pragma once. This file is intended to be included 18 | // multiple times. 19 | 20 | #ifdef UNIFEX_PROLOGUE_HPP 21 | # error Prologue has already been included 22 | #endif 23 | #define UNIFEX_PROLOGUE_HPP 24 | 25 | #include 26 | 27 | UNIFEX_DIAGNOSTIC_PUSH 28 | 29 | #if defined(__clang__) 30 | # pragma clang diagnostic ignored "-Wkeyword-macro" 31 | #endif 32 | 33 | #if UNIFEX_CXX_CONCEPTS 34 | # define template(...) \ 35 | template <__VA_ARGS__> \ 36 | UNIFEX_PP_EXPAND /**/ 37 | #else 38 | # define template(...) template <__VA_ARGS__ UNIFEX_TEMPLATE_SFINAE_AUX_ /**/ 39 | #endif 40 | 41 | UNIFEX_DIAGNOSTIC_POP 42 | 43 | #define AND UNIFEX_AND 44 | -------------------------------------------------------------------------------- /include/unifex/detail/unifex_fwd.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | namespace unifex { 22 | namespace detail { 23 | struct _ignore { 24 | template 25 | /*implicit*/ _ignore(T&&) noexcept {} 26 | }; 27 | 28 | template 29 | struct _empty {}; 30 | } // namespace detail 31 | 32 | namespace _kv { 33 | template 34 | struct _kv { 35 | struct type { 36 | using key_type = Key; 37 | using value_type = Value; 38 | UNIFEX_NO_UNIQUE_ADDRESS Key key; 39 | Value value; 40 | }; 41 | }; 42 | } // namespace _kv 43 | template 44 | using kv = typename _kv::_kv::type; 45 | 46 | namespace _execute::_cpo { 47 | struct _fn; 48 | } // namespace _execute::_cpo 49 | extern const _execute::_cpo::_fn execute; 50 | 51 | namespace _submit_cpo { 52 | extern const struct _fn submit; 53 | } // namespace _submit_cpo 54 | using _submit_cpo::submit; 55 | 56 | namespace _start_cpo { 57 | struct _fn; 58 | } 59 | extern const _start_cpo::_fn start; 60 | 61 | namespace _connect::_cpo { 62 | struct _fn; 63 | } // namespace _connect::_cpo 64 | extern const _connect::_cpo::_fn connect; 65 | 66 | #if !UNIFEX_NO_COROUTINES 67 | namespace _await_tfx { 68 | struct _fn; 69 | } // namespace _await_tfx 70 | extern const _await_tfx::_fn await_transform; 71 | #endif 72 | 73 | namespace _schedule { 74 | struct _fn; 75 | } // namespace _schedule 76 | extern const _schedule::_fn schedule; 77 | 78 | namespace _sf { 79 | template 80 | struct sender_for; 81 | } // namespace _sf 82 | using _sf::sender_for; 83 | 84 | namespace _xchg_cont { 85 | extern const struct _fn exchange_continuation; 86 | } // namespace _xchg_cont 87 | using _xchg_cont::exchange_continuation; 88 | 89 | template 90 | struct sender_traits; 91 | 92 | template 93 | struct sender_traits>; 94 | 95 | } // namespace unifex 96 | -------------------------------------------------------------------------------- /include/unifex/detail/with_abort_tag_invoke.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * (c) Lewis Baker 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | 26 | namespace unifex { 27 | namespace detail { 28 | template 29 | struct _with_abort_tag_invoke; 30 | 31 | template 32 | struct _with_abort_tag_invoke { 33 | [[noreturn]] friend Ret 34 | tag_invoke(CPO, replace_this_t...) noexcept { 35 | std::abort(); 36 | } 37 | }; 38 | 39 | template 40 | struct _with_abort_tag_invoke { 41 | [[noreturn]] friend Ret 42 | tag_invoke(CPO, replace_this_t...) noexcept { 43 | std::abort(); 44 | } 45 | }; 46 | 47 | template 48 | using with_abort_tag_invoke = _with_abort_tag_invoke< 49 | Derived, 50 | base_cpo_t, 51 | typename CPO::type_erased_signature_t>; 52 | } // namespace detail 53 | } // namespace unifex 54 | 55 | #include 56 | -------------------------------------------------------------------------------- /include/unifex/done_as_optional.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace unifex { 31 | namespace _done_as_opt { 32 | namespace _cpo { 33 | inline const struct _fn { 34 | template(typename Sender) // 35 | (requires _single_sender) // 36 | auto 37 | operator()(Sender&& predecessor) const { 38 | using optional_t = std::optional< 39 | non_void_t>>>; 40 | return let_done( 41 | then( 42 | (Sender &&) predecessor, 43 | [](auto&&... ts) noexcept( 44 | noexcept(optional_t{std::in_place, (decltype(ts))ts...})) { 45 | return optional_t{std::in_place, (decltype(ts))ts...}; 46 | }), 47 | []() noexcept { return just(optional_t{}); }); 48 | } 49 | constexpr auto operator()() const noexcept -> bind_back_result_t<_fn> { 50 | return bind_back(*this); 51 | } 52 | } done_as_optional{}; 53 | } // namespace _cpo 54 | } // namespace _done_as_opt 55 | 56 | using _done_as_opt::_cpo::done_as_optional; 57 | 58 | } // namespace unifex 59 | 60 | #include 61 | -------------------------------------------------------------------------------- /include/unifex/execution_policy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | namespace unifex { 21 | // Execution policies are used to describe constraints on the safe execution 22 | // of bulk operations with respect to each other. 23 | // 24 | // sequenced - Operations must be sequenced with respect to each other. 25 | // They are not safe to executed concurrently on differen threads or 26 | // to interleaved with each other on the same thread. 27 | // 28 | // unsequenced - Operations are safe to be interleaved with each other, e.g. 29 | // using vectorised SIMD instructions, but may not be executed 30 | // concurrently on different threads. This generally implies that 31 | // forward progress of one operation is not dependent on forward 32 | // progress of other operations. 33 | // 34 | // parallel - Operations are safe to be executed concurrently with each other on 35 | // different threads but operations on each thread must not be 36 | // interleaved. 37 | // 38 | // parallel_unsequenced - Operations are safe to be executed concurrently on 39 | // different threads and may be interleaved with each 40 | // other on the same thread. 41 | 42 | inline constexpr struct sequenced_policy { 43 | } seq; 44 | inline constexpr struct unsequenced_policy { 45 | } unseq; 46 | inline constexpr struct parallel_policy { 47 | } par; 48 | inline constexpr struct parallel_unsequenced_policy { 49 | } par_unseq; 50 | } // namespace unifex 51 | 52 | #include 53 | -------------------------------------------------------------------------------- /include/unifex/filesystem.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #if __cplusplus >= 201703L 19 | # ifdef __has_include 20 | # if __has_include() 21 | # include 22 | # if __cpp_lib_filesystem >= 201703L && __has_include() 23 | # include 24 | # define UNIFEX_HAVE_FILESYSTEM 1 25 | 26 | namespace unifex { 27 | namespace filesystem { 28 | using std::filesystem::path; 29 | } 30 | } // namespace unifex 31 | # endif 32 | # endif 33 | # ifndef UNIFEX_HAVE_FILESYSTEM 34 | # if __has_include() 35 | # include 36 | # define UNIFEX_HAVE_FILESYSTEM 1 37 | 38 | namespace unifex { 39 | namespace filesystem { 40 | using std::experimental::filesystem::path; 41 | } 42 | } // namespace unifex 43 | # endif 44 | # endif 45 | # endif 46 | #endif 47 | #ifndef UNIFEX_HAVE_FILESYSTEM 48 | # define UNIFEX_HAVE_FILESYSTEM 0 49 | #endif 50 | -------------------------------------------------------------------------------- /include/unifex/fused_stop_source.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | 24 | namespace unifex { 25 | 26 | namespace _fss { 27 | 28 | struct stop_callback { 29 | void operator()() noexcept { source_.request_stop(); } 30 | 31 | unifex::inplace_stop_source& source_; 32 | }; 33 | 34 | template 35 | using stop_callback_t = 36 | typename StopToken::template callback_type; 37 | 38 | template 39 | struct fused_stop_callback { 40 | explicit fused_stop_callback(unifex::inplace_stop_source&) noexcept {} 41 | }; 42 | 43 | template 44 | struct fused_stop_callback { 45 | template 46 | explicit fused_stop_callback( 47 | unifex::inplace_stop_source& source, 48 | StopToken first, 49 | StopTokens... rest) // 50 | noexcept(std::is_nothrow_constructible_v< 51 | fused_stop_callback, 52 | decltype(source), 53 | decltype(rest)...>&& // 54 | std::is_nothrow_constructible_v< 55 | First, 56 | decltype(first), 57 | stop_callback>) 58 | : callback_(std::move(first), stop_callback{source}) 59 | , rest_(source, std::move(rest)...) {} 60 | 61 | UNIFEX_NO_UNIQUE_ADDRESS First callback_; 62 | UNIFEX_NO_UNIQUE_ADDRESS fused_stop_callback rest_; 63 | }; 64 | 65 | template 66 | struct fused_stop_source : unifex::inplace_stop_source { 67 | using fused_callback_type = 68 | fused_stop_callback...>; 69 | 70 | void register_callbacks(StopTokens... tokens) { 71 | callbacks_.emplace(*this, std::move(tokens)...); 72 | } 73 | 74 | void deregister_callbacks() noexcept { callbacks_.reset(); } 75 | 76 | private: 77 | UNIFEX_NO_UNIQUE_ADDRESS std::optional callbacks_; 78 | }; 79 | } // namespace _fss 80 | 81 | using _fss::fused_stop_source; 82 | 83 | } // namespace unifex 84 | 85 | #include 86 | -------------------------------------------------------------------------------- /include/unifex/get_allocator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace unifex { 27 | namespace _get_alloc { 28 | inline const struct _fn { 29 | template 30 | constexpr auto operator()(const T&) const noexcept -> std::enable_if_t< 31 | !is_tag_invocable_v<_fn, const T&>, 32 | std::allocator> { 33 | return std::allocator{}; 34 | } 35 | 36 | template 37 | constexpr auto operator()(const T& object) const noexcept 38 | -> tag_invoke_result_t<_fn, const T&> { 39 | return tag_invoke(*this, object); 40 | } 41 | } get_allocator{}; 42 | } // namespace _get_alloc 43 | 44 | using _get_alloc::get_allocator; 45 | 46 | template 47 | using get_allocator_t = decltype(get_allocator(std::declval())); 48 | 49 | } // namespace unifex 50 | 51 | #include 52 | -------------------------------------------------------------------------------- /include/unifex/get_execution_policy.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | namespace unifex { 24 | namespace _get_execution_policy { 25 | struct _fn { 26 | template(typename PolicyProvider) // 27 | (requires tag_invocable<_fn, const PolicyProvider&>) // 28 | constexpr auto 29 | operator()(const PolicyProvider& provider) const noexcept 30 | -> tag_invoke_result_t<_fn, const PolicyProvider&> { 31 | return tag_invoke(_fn{}, provider); 32 | } 33 | 34 | template(typename PolicyProvider) // 35 | (requires(!tag_invocable<_fn, const PolicyProvider&>)) // 36 | constexpr sequenced_policy 37 | operator()([[maybe_unused]] const PolicyProvider&) const noexcept { 38 | return {}; 39 | } 40 | }; 41 | } // namespace _get_execution_policy 42 | 43 | inline constexpr _get_execution_policy::_fn get_execution_policy{}; 44 | } // namespace unifex 45 | 46 | #include 47 | -------------------------------------------------------------------------------- /include/unifex/invoke.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | 26 | namespace unifex { 27 | 28 | namespace _co_invoke { 29 | inline constexpr struct _fn { 30 | template(typename Fn, typename... Args) // 31 | (requires tag_invocable< 32 | _fn, 33 | type_identity>, 34 | Fn, 35 | Args...>) // 36 | UNIFEX_ALWAYS_INLINE constexpr auto 37 | operator()(Fn&& fn, Args&&... args) const 38 | noexcept(is_nothrow_tag_invocable_v< 39 | _fn, 40 | type_identity>, 41 | Fn, 42 | Args...>) 43 | -> tag_invoke_result_t< 44 | _fn, 45 | type_identity>, 46 | Fn, 47 | Args...> { 48 | return tag_invoke( 49 | *this, 50 | type_identity>{}, 51 | (Fn &&) fn, 52 | (Args &&) args...); 53 | } 54 | } co_invoke{}; 55 | } // namespace _co_invoke 56 | 57 | using _co_invoke::co_invoke; 58 | 59 | } // namespace unifex 60 | 61 | #include 62 | -------------------------------------------------------------------------------- /include/unifex/just_done.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace unifex { 32 | namespace _just_done { 33 | 34 | template 35 | struct _op { 36 | struct type; 37 | }; 38 | template 39 | using operation = typename _op>::type; 40 | 41 | template 42 | struct _op::type { 43 | UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; 44 | 45 | void start() & noexcept { unifex::set_done((Receiver &&) receiver_); } 46 | }; 47 | 48 | class sender { 49 | public: 50 | template < 51 | template 52 | class Variant, 53 | template 54 | class Tuple> 55 | using value_types = Variant<>; 56 | 57 | template