├── .clang-format ├── .github ├── CODEOWNERS └── workflows │ ├── linux.yml │ └── macos.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE.txt ├── Makefile ├── README.md ├── bin ├── mk-compiler-explorer.py └── update-cmake-headers.py ├── cmake └── Config.cmake.in ├── docs └── cppcon-2024-slides.pdf ├── etc ├── ci-clang-toolchain.cmake ├── clang-16-toolchain.cmake ├── clang-17-toolchain.cmake ├── clang-18-toolchain.cmake ├── clang-19-toolchain.cmake ├── clang-flags.cmake ├── clang-toolchain.cmake ├── gcc-11-toolchain.cmake ├── gcc-12-toolchain.cmake ├── gcc-13-toolchain.cmake ├── gcc-14-toolchain.cmake ├── gcc-flags.cmake ├── gcc-toolchain.cmake ├── llvm-16-toolchain.cmake ├── llvm-master-toolchain.cmake ├── llvm-toolchain.cmake └── toolchain.cmake ├── examples ├── CMakeLists.txt ├── client.cpp ├── cppcon-2024.cpp ├── data │ ├── favicon.ico │ ├── index-milano.html │ ├── index.html │ ├── itcpp.png │ └── logo.png ├── demo_algorithm.hpp ├── demo_error.hpp ├── demo_scope.hpp ├── demo_task.hpp ├── empty.cpp ├── http-server.cpp ├── milano.cpp ├── server.cpp └── task.cpp ├── include └── beman │ ├── net │ ├── detail │ │ ├── basic_socket.hpp │ │ ├── basic_socket_acceptor.hpp │ │ ├── basic_stream_socket.hpp │ │ ├── buffer.hpp │ │ ├── container.hpp │ │ ├── context_base.hpp │ │ ├── endpoint.hpp │ │ ├── event_type.hpp │ │ ├── execution.hpp │ │ ├── internet.hpp │ │ ├── io_base.hpp │ │ ├── io_context.hpp │ │ ├── io_context_scheduler.hpp │ │ ├── netfwd.hpp │ │ ├── operations.hpp │ │ ├── poll_context.hpp │ │ ├── sender.hpp │ │ ├── socket_base.hpp │ │ ├── socket_category.hpp │ │ ├── sorted_list.hpp │ │ ├── stop_token.hpp │ │ └── timer.hpp │ └── net.hpp │ └── net29 │ └── net.hpp ├── src └── beman │ └── net │ ├── CMakeLists.txt │ └── net.cpp └── tests └── beman └── net ├── CMakeLists.txt └── sorted_list.pass.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignArrayOfStructures: None 6 | AlignConsecutiveAssignments: 7 | Enabled: true 8 | AcrossEmptyLines: false 9 | AcrossComments: false 10 | AlignCompound: false 11 | PadOperators: true 12 | AlignConsecutiveBitFields: 13 | Enabled: false 14 | AcrossEmptyLines: false 15 | AcrossComments: false 16 | AlignCompound: false 17 | PadOperators: false 18 | AlignConsecutiveDeclarations: 19 | Enabled: true 20 | AcrossEmptyLines: false 21 | AcrossComments: false 22 | AlignCompound: false 23 | PadOperators: true 24 | AlignConsecutiveMacros: 25 | Enabled: false 26 | AcrossEmptyLines: false 27 | AcrossComments: false 28 | AlignCompound: false 29 | PadOperators: false 30 | AlignConsecutiveShortCaseStatements: 31 | Enabled: false 32 | AcrossEmptyLines: false 33 | AcrossComments: false 34 | AlignCaseColons: false 35 | AlignEscapedNewlines: Left 36 | AlignOperands: Align 37 | AlignTrailingComments: 38 | Kind: Always 39 | OverEmptyLines: 0 40 | AllowAllArgumentsOnNextLine: true 41 | AllowAllParametersOfDeclarationOnNextLine: true 42 | AllowShortBlocksOnASingleLine: Never 43 | AllowShortCaseLabelsOnASingleLine: false 44 | AllowShortEnumsOnASingleLine: true 45 | AllowShortFunctionsOnASingleLine: All 46 | AllowShortIfStatementsOnASingleLine: Never 47 | AllowShortLambdasOnASingleLine: All 48 | AllowShortLoopsOnASingleLine: false 49 | AlwaysBreakAfterDefinitionReturnType: None 50 | AlwaysBreakAfterReturnType: None 51 | AlwaysBreakBeforeMultilineStrings: false 52 | AlwaysBreakTemplateDeclarations: Yes 53 | AttributeMacros: 54 | - __capability 55 | BinPackArguments: false 56 | BinPackParameters: false 57 | BitFieldColonSpacing: Both 58 | BraceWrapping: 59 | AfterCaseLabel: false 60 | AfterClass: false 61 | AfterControlStatement: Never 62 | AfterEnum: false 63 | AfterExternBlock: false 64 | AfterFunction: false 65 | AfterNamespace: false 66 | AfterObjCDeclaration: false 67 | AfterStruct: false 68 | AfterUnion: false 69 | BeforeCatch: false 70 | BeforeElse: false 71 | BeforeLambdaBody: false 72 | BeforeWhile: false 73 | IndentBraces: false 74 | SplitEmptyFunction: true 75 | SplitEmptyRecord: true 76 | SplitEmptyNamespace: true 77 | BreakAfterAttributes: Never 78 | BreakAfterJavaFieldAnnotations: false 79 | BreakArrays: true 80 | BreakBeforeBinaryOperators: None 81 | BreakBeforeConceptDeclarations: Always 82 | BreakBeforeBraces: Custom 83 | BreakBeforeInlineASMColon: OnlyMultiline 84 | BreakBeforeTernaryOperators: true 85 | BreakConstructorInitializers: BeforeColon 86 | BreakInheritanceList: BeforeColon 87 | BreakStringLiterals: true 88 | ColumnLimit: 119 89 | CommentPragmas: '^ IWYU pragma:' 90 | CompactNamespaces: false 91 | ConstructorInitializerIndentWidth: 4 92 | ContinuationIndentWidth: 4 93 | Cpp11BracedListStyle: true 94 | DerivePointerAlignment: false 95 | DisableFormat: false 96 | EmptyLineAfterAccessModifier: Never 97 | EmptyLineBeforeAccessModifier: LogicalBlock 98 | ExperimentalAutoDetectBinPacking: false 99 | FixNamespaceComments: true 100 | ForEachMacros: 101 | - foreach 102 | - Q_FOREACH 103 | - BOOST_FOREACH 104 | IfMacros: 105 | - KJ_IF_MAYBE 106 | IncludeBlocks: Preserve 107 | IncludeCategories: 108 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 109 | Priority: 2 110 | SortPriority: 0 111 | CaseSensitive: false 112 | - Regex: '^(<|"(gtest|isl|json)/)' 113 | Priority: 3 114 | SortPriority: 0 115 | CaseSensitive: false 116 | - Regex: '.*' 117 | Priority: 1 118 | SortPriority: 0 119 | CaseSensitive: false 120 | IncludeIsMainRegex: '$' 121 | IncludeIsMainSourceRegex: '' 122 | IndentAccessModifiers: false 123 | IndentCaseBlocks: false 124 | IndentCaseLabels: false 125 | IndentExternBlock: AfterExternBlock 126 | IndentGotoLabels: true 127 | IndentPPDirectives: None 128 | IndentRequiresClause: true 129 | IndentWidth: 4 130 | IndentWrappedFunctionNames: false 131 | InsertBraces: false 132 | InsertNewlineAtEOF: false 133 | InsertTrailingCommas: None 134 | IntegerLiteralSeparator: 135 | Binary: 0 136 | BinaryMinDigits: 0 137 | Decimal: 0 138 | DecimalMinDigits: 0 139 | Hex: 0 140 | HexMinDigits: 0 141 | JavaScriptQuotes: Leave 142 | JavaScriptWrapImports: true 143 | KeepEmptyLinesAtTheStartOfBlocks: true 144 | KeepEmptyLinesAtEOF: false 145 | LambdaBodyIndentation: Signature 146 | LineEnding: DeriveLF 147 | MacroBlockBegin: '' 148 | MacroBlockEnd: '' 149 | MaxEmptyLinesToKeep: 1 150 | NamespaceIndentation: None 151 | ObjCBinPackProtocolList: Auto 152 | ObjCBlockIndentWidth: 4 153 | ObjCBreakBeforeNestedBlockParam: true 154 | ObjCSpaceAfterProperty: false 155 | ObjCSpaceBeforeProtocolList: true 156 | PackConstructorInitializers: NextLine 157 | PenaltyBreakAssignment: 2 158 | PenaltyBreakBeforeFirstCallParameter: 19 159 | PenaltyBreakComment: 300 160 | PenaltyBreakFirstLessLess: 120 161 | PenaltyBreakOpenParenthesis: 0 162 | PenaltyBreakString: 1000 163 | PenaltyBreakTemplateDeclaration: 10 164 | PenaltyExcessCharacter: 1000000 165 | PenaltyIndentedWhitespace: 0 166 | PenaltyReturnTypeOnItsOwnLine: 60 167 | PointerAlignment: Left 168 | PPIndentWidth: -1 169 | QualifierAlignment: Custom 170 | QualifierOrder: 171 | - inline 172 | - static 173 | - constexpr 174 | - const 175 | - volatile 176 | - type 177 | ReferenceAlignment: Pointer 178 | ReflowComments: true 179 | RemoveBracesLLVM: false 180 | RemoveParentheses: Leave 181 | RemoveSemicolon: false 182 | RequiresClausePosition: OwnLine 183 | RequiresExpressionIndentation: OuterScope 184 | SeparateDefinitionBlocks: Leave 185 | ShortNamespaceLines: 1 186 | SortIncludes: Never 187 | SortJavaStaticImport: Before 188 | SortUsingDeclarations: LexicographicNumeric 189 | SpaceAfterCStyleCast: false 190 | SpaceAfterLogicalNot: false 191 | SpaceAfterTemplateKeyword: true 192 | SpaceAroundPointerQualifiers: Default 193 | SpaceBeforeAssignmentOperators: true 194 | SpaceBeforeCaseColon: false 195 | SpaceBeforeCpp11BracedList: false 196 | SpaceBeforeCtorInitializerColon: true 197 | SpaceBeforeInheritanceColon: true 198 | SpaceBeforeJsonColon: false 199 | SpaceBeforeParens: ControlStatements 200 | SpaceBeforeParensOptions: 201 | AfterControlStatements: true 202 | AfterForeachMacros: true 203 | AfterFunctionDefinitionName: false 204 | AfterFunctionDeclarationName: false 205 | AfterIfMacros: true 206 | AfterOverloadedOperator: false 207 | AfterRequiresInClause: false 208 | AfterRequiresInExpression: false 209 | BeforeNonEmptyParentheses: false 210 | SpaceBeforeRangeBasedForLoopColon: true 211 | SpaceBeforeSquareBrackets: false 212 | SpaceInEmptyBlock: false 213 | SpacesBeforeTrailingComments: 1 214 | SpacesInAngles: Never 215 | SpacesInContainerLiterals: true 216 | SpacesInLineCommentPrefix: 217 | Minimum: 1 218 | Maximum: -1 219 | SpacesInParens: Never 220 | SpacesInParensOptions: 221 | InCStyleCasts: false 222 | InConditionalStatements: false 223 | InEmptyParentheses: false 224 | Other: false 225 | SpacesInSquareBrackets: false 226 | Standard: Auto 227 | StatementAttributeLikeMacros: 228 | - Q_EMIT 229 | StatementMacros: 230 | - Q_UNUSED 231 | - QT_REQUIRE_VERSION 232 | TabWidth: 8 233 | UseTab: Never 234 | VerilogBreakBetweenInstancePorts: true 235 | WhitespaceSensitiveMacros: 236 | - STRINGIZE 237 | - PP_STRINGIZE 238 | - BOOST_PP_STRINGIZE 239 | - NS_SWIFT_NAME 240 | - CF_SWIFT_NAME 241 | ... 242 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # code owners for reviews on PRs 2 | 3 | * @dietmarkuehl @camio @bemanproject/core-reviewers 4 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/linux.yml 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | name: Linux Build 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | paths: 10 | - "**.hpp" 11 | - "**.cpp" 12 | - "**/CMakeLists.txt" 13 | - ".github/workflows/linux.yml" 14 | pull_request: 15 | branches: [ "main" ] 16 | paths: 17 | - "**.hpp" 18 | - "**.cpp" 19 | - "**/CMakeLists.txt" 20 | - ".github/workflows/linux.yml" 21 | 22 | jobs: 23 | build: 24 | runs-on: ubuntu-latest 25 | strategy: 26 | matrix: 27 | sanitizer: [none, asan, usan] 28 | compiler: [g++] 29 | steps: 30 | - uses: actions/checkout@v4 31 | - name: Linux ${{ matrix.compiler }} ${{ matrix.sanitizer }} 32 | run: make ${{ matrix.sanitizer }} CXX=${{ matrix.compiler }} 33 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/macos.yml 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | name: Macos Build 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | paths: 10 | - "**.hpp" 11 | - "**.cpp" 12 | - "**/CMakeLists.txt" 13 | - ".github/workflows/macos.yml" 14 | pull_request: 15 | branches: [ "main" ] 16 | paths: 17 | - "**.hpp" 18 | - "**.cpp" 19 | - "**/CMakeLists.txt" 20 | - ".github/workflows/macos.yml" 21 | 22 | jobs: 23 | build: 24 | runs-on: macos-latest 25 | steps: 26 | - uses: actions/checkout@v4 27 | - name: make 28 | run: make 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build 35 | .cache 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake-format: off 2 | # /CMakeLists.txt -*-makefile-*- 3 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | # cmake-format: on 5 | 6 | cmake_minimum_required(VERSION 3.23) 7 | project(beman_net VERSION 0.0.0 LANGUAGES CXX) 8 | set(TARGET_NAME net) 9 | set(TARGET_PREFIX beman.${TARGET_NAME}) 10 | set(TARGET_LIBRARY beman_${TARGET_NAME}) 11 | set(TARGET_ALIAS beman::${TARGET_NAME}) 12 | set(TARGETS_EXPORT_NAME ${CMAKE_PROJECT_NAME}) 13 | 14 | set(CMAKE_CXX_STANDARD 23) 15 | 16 | include(FetchContent) 17 | FetchContent_Declare( 18 | execution 19 | # for local development, use SOURCE_DIR /execution 20 | GIT_REPOSITORY https://github.com/bemanproject/execution 21 | GIT_TAG e9c3032 22 | ) 23 | FetchContent_MakeAvailable(execution) 24 | 25 | include(CTest) 26 | if(BUILD_TESTING) 27 | add_subdirectory(tests/beman/${TARGET_NAME}) 28 | enable_testing() 29 | endif() 30 | 31 | add_subdirectory(src/beman/${TARGET_NAME}) 32 | add_subdirectory(examples) 33 | 34 | include(GNUInstallDirs) 35 | 36 | set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake) 37 | 38 | include(CMakePackageConfigHelpers) 39 | 40 | write_basic_package_version_file( 41 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake 42 | VERSION ${PROJECT_VERSION} 43 | COMPATIBILITY AnyNewerVersion) 44 | 45 | configure_package_config_file( 46 | "cmake/Config.cmake.in" 47 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake 48 | INSTALL_DESTINATION ${INSTALL_CONFIGDIR}) 49 | 50 | install( 51 | FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake 52 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake 53 | DESTINATION ${INSTALL_CONFIGDIR}) 54 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | The Beman Project is under the Apache License v2.0 with LLVM Exceptions: 3 | ============================================================================== 4 | 5 | Apache License 6 | Version 2.0, January 2004 7 | http://www.apache.org/licenses/ 8 | 9 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 10 | 11 | 1. Definitions. 12 | 13 | "License" shall mean the terms and conditions for use, reproduction, 14 | and distribution as defined by Sections 1 through 9 of this document. 15 | 16 | "Licensor" shall mean the copyright owner or entity authorized by 17 | the copyright owner that is granting the License. 18 | 19 | "Legal Entity" shall mean the union of the acting entity and all 20 | other entities that control, are controlled by, or are under common 21 | control with that entity. For the purposes of this definition, 22 | "control" means (i) the power, direct or indirect, to cause the 23 | direction or management of such entity, whether by contract or 24 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 25 | outstanding shares, or (iii) beneficial ownership of such entity. 26 | 27 | "You" (or "Your") shall mean an individual or Legal Entity 28 | exercising permissions granted by this License. 29 | 30 | "Source" form shall mean the preferred form for making modifications, 31 | including but not limited to software source code, documentation 32 | source, and configuration files. 33 | 34 | "Object" form shall mean any form resulting from mechanical 35 | transformation or translation of a Source form, including but 36 | not limited to compiled object code, generated documentation, 37 | and conversions to other media types. 38 | 39 | "Work" shall mean the work of authorship, whether in Source or 40 | Object form, made available under the License, as indicated by a 41 | copyright notice that is included in or attached to the work 42 | (an example is provided in the Appendix below). 43 | 44 | "Derivative Works" shall mean any work, whether in Source or Object 45 | form, that is based on (or derived from) the Work and for which the 46 | editorial revisions, annotations, elaborations, or other modifications 47 | represent, as a whole, an original work of authorship. For the purposes 48 | of this License, Derivative Works shall not include works that remain 49 | separable from, or merely link (or bind by name) to the interfaces of, 50 | the Work and Derivative Works thereof. 51 | 52 | "Contribution" shall mean any work of authorship, including 53 | the original version of the Work and any modifications or additions 54 | to that Work or Derivative Works thereof, that is intentionally 55 | submitted to Licensor for inclusion in the Work by the copyright owner 56 | or by an individual or Legal Entity authorized to submit on behalf of 57 | the copyright owner. For the purposes of this definition, "submitted" 58 | means any form of electronic, verbal, or written communication sent 59 | to the Licensor or its representatives, including but not limited to 60 | communication on electronic mailing lists, source code control systems, 61 | and issue tracking systems that are managed by, or on behalf of, the 62 | Licensor for the purpose of discussing and improving the Work, but 63 | excluding communication that is conspicuously marked or otherwise 64 | designated in writing by the copyright owner as "Not a Contribution." 65 | 66 | "Contributor" shall mean Licensor and any individual or Legal Entity 67 | on behalf of whom a Contribution has been received by Licensor and 68 | subsequently incorporated within the Work. 69 | 70 | 2. Grant of Copyright License. Subject to the terms and conditions of 71 | this License, each Contributor hereby grants to You a perpetual, 72 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 73 | copyright license to reproduce, prepare Derivative Works of, 74 | publicly display, publicly perform, sublicense, and distribute the 75 | Work and such Derivative Works in Source or Object form. 76 | 77 | 3. Grant of Patent License. Subject to the terms and conditions of 78 | this License, each Contributor hereby grants to You a perpetual, 79 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 80 | (except as stated in this section) patent license to make, have made, 81 | use, offer to sell, sell, import, and otherwise transfer the Work, 82 | where such license applies only to those patent claims licensable 83 | by such Contributor that are necessarily infringed by their 84 | Contribution(s) alone or by combination of their Contribution(s) 85 | with the Work to which such Contribution(s) was submitted. If You 86 | institute patent litigation against any entity (including a 87 | cross-claim or counterclaim in a lawsuit) alleging that the Work 88 | or a Contribution incorporated within the Work constitutes direct 89 | or contributory patent infringement, then any patent licenses 90 | granted to You under this License for that Work shall terminate 91 | as of the date such litigation is filed. 92 | 93 | 4. Redistribution. You may reproduce and distribute copies of the 94 | Work or Derivative Works thereof in any medium, with or without 95 | modifications, and in Source or Object form, provided that You 96 | meet the following conditions: 97 | 98 | (a) You must give any other recipients of the Work or 99 | Derivative Works a copy of this License; and 100 | 101 | (b) You must cause any modified files to carry prominent notices 102 | stating that You changed the files; and 103 | 104 | (c) You must retain, in the Source form of any Derivative Works 105 | that You distribute, all copyright, patent, trademark, and 106 | attribution notices from the Source form of the Work, 107 | excluding those notices that do not pertain to any part of 108 | the Derivative Works; and 109 | 110 | (d) If the Work includes a "NOTICE" text file as part of its 111 | distribution, then any Derivative Works that You distribute must 112 | include a readable copy of the attribution notices contained 113 | within such NOTICE file, excluding those notices that do not 114 | pertain to any part of the Derivative Works, in at least one 115 | of the following places: within a NOTICE text file distributed 116 | as part of the Derivative Works; within the Source form or 117 | documentation, if provided along with the Derivative Works; or, 118 | within a display generated by the Derivative Works, if and 119 | wherever such third-party notices normally appear. The contents 120 | of the NOTICE file are for informational purposes only and 121 | do not modify the License. You may add Your own attribution 122 | notices within Derivative Works that You distribute, alongside 123 | or as an addendum to the NOTICE text from the Work, provided 124 | that such additional attribution notices cannot be construed 125 | as modifying the License. 126 | 127 | You may add Your own copyright statement to Your modifications and 128 | may provide additional or different license terms and conditions 129 | for use, reproduction, or distribution of Your modifications, or 130 | for any such Derivative Works as a whole, provided Your use, 131 | reproduction, and distribution of the Work otherwise complies with 132 | the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, 135 | any Contribution intentionally submitted for inclusion in the Work 136 | by You to the Licensor shall be under the terms and conditions of 137 | this License, without any additional terms or conditions. 138 | Notwithstanding the above, nothing herein shall supersede or modify 139 | the terms of any separate license agreement you may have executed 140 | with Licensor regarding such Contributions. 141 | 142 | 6. Trademarks. This License does not grant permission to use the trade 143 | names, trademarks, service marks, or product names of the Licensor, 144 | except as required for reasonable and customary use in describing the 145 | origin of the Work and reproducing the content of the NOTICE file. 146 | 147 | 7. Disclaimer of Warranty. Unless required by applicable law or 148 | agreed to in writing, Licensor provides the Work (and each 149 | Contributor provides its Contributions) on an "AS IS" BASIS, 150 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 151 | implied, including, without limitation, any warranties or conditions 152 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 153 | PARTICULAR PURPOSE. You are solely responsible for determining the 154 | appropriateness of using or redistributing the Work and assume any 155 | risks associated with Your exercise of permissions under this License. 156 | 157 | 8. Limitation of Liability. In no event and under no legal theory, 158 | whether in tort (including negligence), contract, or otherwise, 159 | unless required by applicable law (such as deliberate and grossly 160 | negligent acts) or agreed to in writing, shall any Contributor be 161 | liable to You for damages, including any direct, indirect, special, 162 | incidental, or consequential damages of any character arising as a 163 | result of this License or out of the use or inability to use the 164 | Work (including but not limited to damages for loss of goodwill, 165 | work stoppage, computer failure or malfunction, or any and all 166 | other commercial damages or losses), even if such Contributor 167 | has been advised of the possibility of such damages. 168 | 169 | 9. Accepting Warranty or Additional Liability. While redistributing 170 | the Work or Derivative Works thereof, You may choose to offer, 171 | and charge a fee for, acceptance of support, warranty, indemnity, 172 | or other liability obligations and/or rights consistent with this 173 | License. However, in accepting such obligations, You may act only 174 | on Your own behalf and on Your sole responsibility, not on behalf 175 | of any other Contributor, and only if You agree to indemnify, 176 | defend, and hold each Contributor harmless for any liability 177 | incurred by, or claims asserted against, such Contributor by reason 178 | of your accepting any such warranty or additional liability. 179 | 180 | END OF TERMS AND CONDITIONS 181 | 182 | APPENDIX: How to apply the Apache License to your work. 183 | 184 | To apply the Apache License to your work, attach the following 185 | boilerplate notice, with the fields enclosed by brackets "[]" 186 | replaced with your own identifying information. (Don't include 187 | the brackets!) The text should be enclosed in the appropriate 188 | comment syntax for the file format. We also recommend that a 189 | file or class name and description of purpose be included on the 190 | same "printed page" as the copyright notice for easier 191 | identification within third-party archives. 192 | 193 | Copyright [yyyy] [name of copyright owner] 194 | 195 | Licensed under the Apache License, Version 2.0 (the "License"); 196 | you may not use this file except in compliance with the License. 197 | You may obtain a copy of the License at 198 | 199 | http://www.apache.org/licenses/LICENSE-2.0 200 | 201 | Unless required by applicable law or agreed to in writing, software 202 | distributed under the License is distributed on an "AS IS" BASIS, 203 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 204 | See the License for the specific language governing permissions and 205 | limitations under the License. 206 | 207 | 208 | ---- LLVM Exceptions to the Apache 2.0 License ---- 209 | 210 | As an exception, if, as a result of your compiling your source code, portions 211 | of this Software are embedded into an Object form of such source code, you 212 | may redistribute such embedded portions in such Object form without complying 213 | with the conditions of Sections 4(a), 4(b) and 4(d) of the License. 214 | 215 | In addition, if you combine or link compiled forms of this Software with 216 | software that is licensed under the GPLv2 ("Combined Software") and if a 217 | court of competent jurisdiction determines that the patent provision (Section 218 | 3), the indemnity provision (Section 9) or other Section of the License 219 | conflicts with the conditions of the GPLv2, you may retroactively and 220 | prospectively choose to deem waived or otherwise exclude such Section(s) of 221 | the License, but only in their entirety and only with respect to the Combined 222 | Software. 223 | 224 | ============================================================================== 225 | Software from third parties included in the Beman Project: 226 | ============================================================================== 227 | The Beman Project contains third party software which is under different license 228 | terms. All such code will be identified clearly using at least one of two 229 | mechanisms: 230 | 1) It will be in a separate directory tree with its own `LICENSE.txt` or 231 | `LICENSE` file at the top containing the specific license and restrictions 232 | which apply to that software, or 233 | 2) It will contain specific license and restriction terms at the top of every 234 | file. 235 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | SANITIZERS = none debug msan asan usan tsan 5 | .PHONY: default gcc clang run update check ce todo distclean clean build test all format $(SANITIZERS) 6 | 7 | COMPILER=system 8 | CXX_BASE=$(CXX:$(dir $(CXX))%=%) 9 | ifeq ($(CXX_BASE),g++) 10 | COMPILER=gcc 11 | endif 12 | ifeq ($(CXX_BASE),clang++) 13 | COMPILER=clang 14 | endif 15 | 16 | CXX_FLAGS = -g 17 | SANITIZER = none 18 | SOURCEDIR = $(shell pwd) 19 | BUILDROOT = build 20 | BUILD = $(BUILDROOT)/$(COMPILER)/$(SANITIZER) 21 | EXAMPLE = server 22 | CMAKE_C_COMPILER=$(COMPILER) 23 | CMAKE_CXX_COMPILER=$(COMPILER) 24 | 25 | ifeq ($(SANITIZER),none) 26 | CXX_FLAGS = -O3 -pedantic -Wall -Wextra -Werror 27 | endif 28 | ifeq ($(SANITIZER),debug) 29 | CXX_FLAGS = -g 30 | endif 31 | ifeq ($(SANITIZER),usan) 32 | SAN_FLAGS = -fsanitize=memory 33 | endif 34 | ifeq ($(SANITIZER),asan) 35 | SAN_FLAGS = -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize-address-use-after-scope 36 | endif 37 | ifeq ($(SANITIZER),usan) 38 | SAN_FLAGS = -fsanitize=undefined 39 | endif 40 | ifeq ($(SANITIZER),tsan) 41 | SAN_FLAGS = -fsanitize=thread 42 | endif 43 | ifeq ($(SANITIZER),lsan) 44 | SAN_FLAGS = -fsanitize=leak 45 | endif 46 | 47 | default: build 48 | 49 | all: $(SANITIZERS) 50 | 51 | gcc: 52 | $(MAKE) CXX=/opt/gcc-14.1.0/bin/g++ 53 | 54 | clang: 55 | $(MAKE) CXX=/opt/llvm-18.1.8/bin/clang++ 56 | 57 | run: build 58 | ./$(BUILD)/examples/$(EXAMPLE) 59 | 60 | none: test 61 | 62 | $(SANITIZERS): 63 | $(MAKE) SANITIZER=$@ 64 | 65 | build: 66 | @mkdir -p $(BUILD) 67 | cd $(BUILD); CC=$(CXX) cmake $(SOURCEDIR) $(TOOLCHAIN) $(SYSROOT) -DCMAKE_CXX_COMPILER=$(CXX) -DCMAKE_CXX_FLAGS="$(CXX_FLAGS) $(SAN_FLAGS)" 68 | cmake --build $(BUILD) 69 | 70 | test: build 71 | cd $(BUILD); $(MAKE) test 72 | 73 | ce: 74 | @mkdir -p $(BUILD) 75 | bin/mk-compiler-explorer.py $(BUILD) 76 | 77 | SOURCE_CMAKELISTS = src/beman/net/CMakeLists.txt 78 | update: 79 | bin/update-cmake-headers.py $(SOURCE_CMAKELISTS) 80 | 81 | check: 82 | @for h in `find include -name \*.hpp`; \ 83 | do \ 84 | from=`echo -n $$h | sed -n 's@.*Beman/\(.*\).hpp.*@\1@p'`; \ 85 | < $$h sed -n "/^ *# *include .*@$$from \1@p"; \ 86 | done | tsort > /dev/null 87 | 88 | todo: 89 | bin/mk-todo.py 90 | 91 | format: 92 | git clang-format main 93 | 94 | clean: 95 | $(RM) -r $(BUILD) 96 | $(RM) mkerr olderr *~ 97 | 98 | distclean: clean 99 | $(RM) -r $(BUILDROOT) 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # beman.net: Senders For Network Operations 2 | 3 | 4 | 5 | `beman.net` provides senders for asynchronous network operations. 6 | It is based on [P2762R2](https://wg21.link/P2762R2). Both the proposal 7 | and the implementation are in an early state although basic 8 | functionality is provided. 9 | 10 | `beman.net` builds on top of [`beman.execution26`](https://github.com/bemanproject/execution26). The 11 | implementation should allow multiple ways how to support asynchronous 12 | operations although currently the only implemented approach is based 13 | on `poll(2)`. Implementations using `kqueue(2)`, `epoll(2)`, 14 | `io_uring`, and IOCP hopefully follow soon. It should also be 15 | possible use various libraries for asynchronous operations like 16 | `libevent`, `libuv`, etc. 17 | 18 | **Implements**: [Sender/Receiver Interface for Networking (P2762R2)](https://wg21.link/P2762R2) 19 | 20 | **Status**: [Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/BEMAN_LIBRARY_MATURITY_MODEL.md#under-development-and-not-yet-ready-for-production-use) 21 | 22 | ## Help Welcome! 23 | 24 | There are plenty of things which need to be done. Some of these 25 | are listed in the [issues section](https://github.com/bemanproject/net/issues). 26 | Other contributions are, of course, also welcome. Aside from contributing 27 | code the project welcomes reports on usage experience, code reviews, defect 28 | reports, features requests, etc. There are plenty contribution opportunities. 29 | 30 | If you want to contribute, you won't be left alone! Please e-mail 31 | [Dietmar Kühl](mailto:dietmar.kuehl@me.com) if want help or mentoring 32 | for contributing to the library. 33 | 34 | ## State of the Proposal 35 | 36 | At the February 2024/Tokyo meeting the Networking SG4 discussion 37 | recommended _not_ to provide a low-level interface for networking! 38 | Instead, a [IETF TAPS](https://datatracker.ietf.org/wg/taps/documents/) 39 | based implementation should be used. As a result, the shape of the 40 | interface will be different. However, even if the public interface 41 | is using [IETF TAPS](https://datatracker.ietf.org/wg/taps/documents/) 42 | the implementation will use a lower-level interface which can likely 43 | use something akin to the current interface. 44 | 45 | ## Building 46 | 47 | Currently, the interfaces are entirely implemented in headers, i.e., 48 | there isn't a library needed. However, using the library `libbeman_net` 49 | should make the relevant paths to headers available. The following 50 | instructions build the library and the examples (required libraries are 51 | obtained and build using these instructions): 52 | 53 | cmake -B build 54 | cmake --build build 55 | 56 | The code is working on MacOS building with the system's 57 | [`clang`](https://clang.llvm.org/) and recent [`gcc`](http://gcc.gnu.org/). 58 | It should hopefully also work on Linux but it isn't tested, yet. 59 | Windows isn't supported, yet, primarily because the relevant class 60 | for the networking operations are different. 61 | -------------------------------------------------------------------------------- /bin/mk-compiler-explorer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # bin/mk-compiler-explorer.py 3 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | 5 | import glob 6 | import os 7 | import re 8 | import sys 9 | 10 | head_re = re.compile("include/(?P.*)\.hpp") 11 | def clean_name(file): 12 | match = head_re.match(file) 13 | return match.group("name") 14 | 15 | top = [] 16 | for toplevel in glob.glob('include/beman/*/*.hpp'): 17 | top.append(clean_name(toplevel)) 18 | 19 | all = top.copy() 20 | for detail in glob.glob('include/beman/*/detail/*.hpp'): 21 | all.append(clean_name(detail)) 22 | for dep in glob.glob('build/_deps/*/include/beman/*/*.hpp'): 23 | all.append(clean_name(dep)) 24 | for dep in glob.glob('build/_deps/*/include/beman/*/betail/*.hpp'): 25 | all.append(clean_name(dep)) 26 | 27 | headers = {} 28 | beman_re = re.compile('#include ["<](?P[bB]eman/.*)\.hpp[">]') 29 | other_re = re.compile('#include ["<](?P.*)[">]') 30 | 31 | def get_dependencies(component): 32 | deps = [] 33 | with open("include/" + component + ".hpp") as file: 34 | for line in file.readlines(): 35 | if beman_re.match(line): 36 | deps.append(beman_re.match(line).group("name")) 37 | elif (other_re.match(line)): 38 | header = other_re.match(line).group("name") 39 | if header not in headers: 40 | headers[header] = 1 41 | 42 | return deps 43 | 44 | dependencies = {} 45 | 46 | for component in all: 47 | dependencies[component] = get_dependencies(component) 48 | 49 | if len(sys.argv) != 2: 50 | print(f'usage: {sys.argv[0]} ') 51 | sys.exit(1) 52 | 53 | dir = sys.argv[1] 54 | 55 | project_re = re.compile("(?P(?P[bB]eman)/.*)/") 56 | define_re = re.compile("#define") 57 | 58 | def write_header(to, header): 59 | with open(f'include/{header}.hpp') as file: 60 | for line in file.readlines(): 61 | if not beman_re.match(line) and not other_re.match(line): 62 | to.write(line) 63 | 64 | def build_header(file, to, header): 65 | includes = list(headers.keys()) 66 | for include in includes: 67 | to.write(f'#include <{include}>\n') 68 | 69 | deps = {} 70 | todo = dependencies[header].copy() 71 | while 0 < len(todo): 72 | if not todo[0] in deps: 73 | deps[todo[0]] = dependencies[todo[0]].copy() 74 | for new in dependencies[todo[0]]: 75 | todo.append(new) 76 | todo = todo[1:] 77 | 78 | while 0 < len(deps): 79 | empty = [item for item in deps.keys() if 0 == len(deps[item])] 80 | for e in empty: 81 | write_header(to, e) 82 | deps.pop(e, None) 83 | for d in deps.keys(): 84 | deps[d] = [item for item in deps[d] if e != item] 85 | 86 | for header in top: 87 | beman = project_re.match(header).group("beman") 88 | if not os.path.exists(f'{dir}/{beman}'): 89 | os.mkdir(f'{dir}/{beman}') 90 | project = project_re.match(header).group("project") 91 | if not os.path.exists(f'{dir}/{project}'): 92 | os.mkdir(f'{dir}/{project}') 93 | 94 | prolog_done = False 95 | with open(f'include/{header}.hpp') as file: 96 | with open(f'{dir}/{header}.hpp', 'w') as to: 97 | for line in file.readlines(): 98 | if not beman_re.match(line) and not other_re.match(line): 99 | to.write(line) 100 | if not prolog_done and define_re.match(line): 101 | prolog_done = True 102 | to.write("\n") 103 | build_header(file, to, header) 104 | to.write("\n") 105 | -------------------------------------------------------------------------------- /bin/update-cmake-headers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # bin/update-cmake-headers.py 3 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | 5 | import glob 6 | import os 7 | import re 8 | import sys 9 | 10 | head_re = re.compile("include/(?P.*)\.hpp") 11 | def clean_name(file): 12 | match = head_re.match(file) 13 | return match.group("name") 14 | 15 | def get_headers(dir): 16 | result = [] 17 | for header in glob.glob(dir + '/*.hpp'): 18 | result.append(clean_name(header)) 19 | result.sort() 20 | return result 21 | 22 | sections = { 23 | 'public': get_headers('include/beman/*'), 24 | 'detail': get_headers('include/beman/*/detail'), 25 | } 26 | 27 | file_set_re = re.compile(" *FILE_SET.*") 28 | section_re = re.compile(" *FILE_SET \${TARGET_LIBRARY}_(?P
.*)_headers TYPE HEADERS") 29 | header_re = re.compile(" *\${PROJECT_SOURCE_DIR}/include/beman/.*/.*\.hpp") 30 | 31 | if len(sys.argv) != 2: 32 | print(f'usage: {sys.argv[0]} /CMakeLists.txt') 33 | sys.exit(1) 34 | 35 | cmake = sys.argv[1] 36 | print(f'updating {cmake}') 37 | 38 | section = "" 39 | section_done = False 40 | 41 | with open(cmake, 'r') as input: 42 | lines = input.readlines() 43 | 44 | with open(f'{cmake}', 'w') as output: 45 | for line in lines: 46 | if None != file_set_re.match(line): 47 | section = "" 48 | match = section_re.match(line) 49 | if None != match: 50 | section = match.group("section") 51 | section_done = False 52 | if None != header_re.match(line): 53 | if not section_done: 54 | section_done = True 55 | project = "${PROJECT_SOURCE_DIR}" 56 | for header in sections[section]: 57 | output.write(f' {project}/include/{header}.hpp\n') 58 | else: 59 | output.write(line) 60 | pass -------------------------------------------------------------------------------- /cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | # cmake/Config.cmake.in -*-makefile-*- 2 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | @PACKAGE_INIT@ 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 7 | check_required_components("@PROJECT_NAME@") 8 | -------------------------------------------------------------------------------- /docs/cppcon-2024-slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bemanproject/net/193d043002143242731f9baf759efc6d624cace7/docs/cppcon-2024-slides.pdf -------------------------------------------------------------------------------- /etc/ci-clang-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang) 4 | set(CMAKE_CXX_COMPILER clang++) 5 | 6 | set(CMAKE_CXX_FLAGS 7 | "-std=c++20 \ 8 | -Wall -Wextra \ 9 | -stdlib=libc++ -fexperimental-library" 10 | CACHE STRING "CXX_FLAGS" FORCE) 11 | 12 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 14 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 15 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 16 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) 17 | -------------------------------------------------------------------------------- /etc/clang-16-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-16) 4 | set(CMAKE_CXX_COMPILER clang++-16) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake") 7 | -------------------------------------------------------------------------------- /etc/clang-17-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-17) 4 | set(CMAKE_CXX_COMPILER clang++-17) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake") 7 | -------------------------------------------------------------------------------- /etc/clang-18-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-18) 4 | set(CMAKE_CXX_COMPILER clang++-18) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake") 7 | -------------------------------------------------------------------------------- /etc/clang-19-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-19) 4 | set(CMAKE_CXX_COMPILER clang++-19) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake") 7 | -------------------------------------------------------------------------------- /etc/clang-flags.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_CXX_STANDARD 23) 4 | 5 | set(CMAKE_CXX_FLAGS 6 | "-stdlib=libc++ -Wall -Wextra " 7 | CACHE STRING "CXX_FLAGS" FORCE) 8 | 9 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 10 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 11 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 12 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" CACHE STRING "C++ ASAN Flags" FORCE) 14 | -------------------------------------------------------------------------------- /etc/clang-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang) 4 | set(CMAKE_CXX_COMPILER clang++) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake") 7 | -------------------------------------------------------------------------------- /etc/gcc-11-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/gcc-flags.cmake") 4 | 5 | set(CMAKE_C_COMPILER gcc-11) 6 | set(CMAKE_CXX_COMPILER g++-11) 7 | -------------------------------------------------------------------------------- /etc/gcc-12-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/gcc-flags.cmake") 4 | 5 | set(CMAKE_C_COMPILER gcc-12) 6 | set(CMAKE_CXX_COMPILER g++-12) 7 | -------------------------------------------------------------------------------- /etc/gcc-13-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/gcc-flags.cmake") 4 | 5 | set(CMAKE_C_COMPILER gcc-13) 6 | set(CMAKE_CXX_COMPILER g++-13) 7 | -------------------------------------------------------------------------------- /etc/gcc-14-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/gcc-flags.cmake") 4 | 5 | set(CMAKE_C_COMPILER gcc-14) 6 | set(CMAKE_CXX_COMPILER g++-14) 7 | -------------------------------------------------------------------------------- /etc/gcc-flags.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_CXX_STANDARD 23) 4 | 5 | set(CMAKE_CXX_FLAGS 6 | "-std=c++23 -Wall -Wextra " 7 | CACHE STRING "CXX_FLAGS" FORCE) 8 | 9 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 10 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 11 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 12 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=undefined" CACHE STRING "C++ ASAN Flags" FORCE) 14 | -------------------------------------------------------------------------------- /etc/gcc-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER gcc) 4 | set(CMAKE_CXX_COMPILER g++) 5 | 6 | set(CMAKE_CXX_FLAGS 7 | "-std=c++20 \ 8 | -Wall -Wextra " 9 | CACHE STRING "CXX_FLAGS" FORCE) 10 | 11 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 12 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 14 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 15 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address,undefined,leak" CACHE STRING "C++ ASAN Flags" FORCE) 16 | -------------------------------------------------------------------------------- /etc/llvm-16-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-16) 4 | set(CMAKE_CXX_COMPILER clang++-16) 5 | 6 | set(CMAKE_CXX_FLAGS 7 | "-std=c++20 \ 8 | -Wall -Wextra \ 9 | -stdlib=libc++ -fexperimental-library" 10 | CACHE STRING "CXX_FLAGS" FORCE) 11 | 12 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 14 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 15 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 16 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) 17 | -------------------------------------------------------------------------------- /etc/llvm-master-toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(LLVM_ROOT "$ENV{LLVM_ROOT}" CACHE PATH "Path to LLVM installation") 2 | 3 | set(CMAKE_C_COMPILER ${LLVM_ROOT}/bin/clang) 4 | set(CMAKE_CXX_COMPILER ${LLVM_ROOT}/bin/clang++) 5 | 6 | set(CMAKE_CXX_FLAGS 7 | "-std=c++2a \ 8 | -Wall -Wextra \ 9 | -stdlib=libc++ " 10 | CACHE STRING "CXX_FLAGS" FORCE) 11 | 12 | set(CMAKE_EXE_LINKER_FLAGS 13 | "-Wl,-rpath,${LLVM_ROOT}/lib" 14 | CACHE STRING "CMAKE_EXE_LINKER_FLAGS" FORCE) 15 | 16 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 17 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 18 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 19 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 20 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) 21 | -------------------------------------------------------------------------------- /etc/llvm-toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | set(CMAKE_C_COMPILER clang-14) 4 | set(CMAKE_CXX_COMPILER clang++-14) 5 | 6 | set(CMAKE_CXX_FLAGS 7 | "-std=c++20 \ 8 | -Wall -Wextra \ 9 | -stdlib=libstdc++ " 10 | CACHE STRING "CXX_FLAGS" FORCE) 11 | 12 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE) 13 | set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -g0 -DNDEBUG" CACHE STRING "C++ Release Flags" FORCE) 14 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG" CACHE STRING "C++ RelWithDebInfo Flags" FORCE) 15 | set(CMAKE_CXX_FLAGS_TSAN "-O3 -g -DNDEBUG -fsanitize=thread" CACHE STRING "C++ TSAN Flags" FORCE) 16 | set(CMAKE_CXX_FLAGS_ASAN "-O3 -g -DNDEBUG -fsanitize=address -fsanitize=undefined -fsanitize=leak" CACHE STRING "C++ ASAN Flags" FORCE) 17 | -------------------------------------------------------------------------------- /etc/toolchain.cmake: -------------------------------------------------------------------------------- 1 | include_guard(GLOBAL) 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/gcc-flags.cmake") 4 | 5 | set(CMAKE_C_COMPILER cc) 6 | set(CMAKE_CXX_COMPILER c++) 7 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake-format: off 2 | # examples/CMakeLists.txt -*-makefile-*- 3 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 | # cmake-format: on 5 | 6 | set(EXAMPLES 7 | client 8 | cppcon-2024 9 | empty 10 | http-server 11 | milano 12 | server 13 | task 14 | ) 15 | 16 | foreach(EXAMPLE ${EXAMPLES}) 17 | set(EXAMPLE_TARGET ${TARGET_PREFIX}.examples.${EXAMPLE}) 18 | add_executable(${EXAMPLE_TARGET}) 19 | target_sources(${EXAMPLE_TARGET} PRIVATE ${EXAMPLE}.cpp) 20 | target_link_libraries(${EXAMPLE_TARGET} PRIVATE ${TARGET_LIBRARY}) 21 | target_link_libraries(${EXAMPLE_TARGET} PRIVATE beman::execution) 22 | endforeach() 23 | -------------------------------------------------------------------------------- /examples/client.cpp: -------------------------------------------------------------------------------- 1 | // examples/client.cpp -*-C++-*- 2 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "demo_task.hpp" 9 | #include "demo_scope.hpp" 10 | 11 | namespace ex = ::beman::execution; 12 | namespace net = ::beman::net; 13 | 14 | // ---------------------------------------------------------------------------- 15 | 16 | namespace { 17 | auto use(auto&&...) -> void {} 18 | } // namespace 19 | 20 | auto main() -> int { 21 | using namespace std::chrono_literals; 22 | using on_exit = std::unique_ptr; 23 | net::io_context context; 24 | demo::scope scope; 25 | 26 | scope.spawn(std::invoke( 27 | [](auto& ctxt) -> demo::task<> { 28 | on_exit msg("5s timer - done"); 29 | co_await net::resume_after(ctxt.get_scheduler(), 5s); 30 | std::cout << "5s timer expired\n"; 31 | }, 32 | context) 33 | // net::resume_after(context.get_scheduler(), 5s) 34 | //| ex::then([]{ std::cout << "5s timer expired\n"; }) 35 | //| ex::upon_stopped([]{ std::cout << "5s timer got cancelled\n"; }) 36 | ); 37 | 38 | auto stop = [&scope, &context] { 39 | scope.spawn(ex::schedule(context.get_scheduler()) | ex::then([] { std::cout << "sending stop\n"; }) | 40 | ex::then([&scope] { scope.stop(); }) | 41 | ex::then([] { std::cout << "task sending stop signal\n"; })); 42 | }; 43 | 44 | scope.spawn(std::invoke( 45 | [](auto& ctxt, auto stp) -> demo::task<> { 46 | on_exit msg("timer task (enqueing stop task) - done"); 47 | co_await net::resume_after(ctxt.get_scheduler(), 1s); 48 | stp(); 49 | }, 50 | context, 51 | stop)); 52 | 53 | scope.spawn(std::invoke( 54 | [](auto& ctxt) -> demo::task<> { 55 | on_exit msg("connecting client - done"); 56 | net::ip::tcp::endpoint ep(net::ip::address_v4::loopback(), 12345); 57 | net::ip::tcp::socket client(ctxt, ep); 58 | 59 | if (false) 60 | for (int i{}; i < 5; ++i) { 61 | std::cout << "i=" << i << "\n"; 62 | co_await net::resume_after(ctxt.get_scheduler(), 1s); 63 | } 64 | 65 | if (not co_await (net::async_connect(client) | ex::then([](auto&&...) { return true; }) | 66 | ex::upon_error([](auto e) { 67 | if constexpr (std::same_as) { 68 | std::error_code f = e; 69 | std::cout << "error_code=" << f.message() << "\n"; 70 | } else if constexpr (std::same_as) 71 | ; 72 | else 73 | static_assert(std::same_as); 74 | return false; 75 | }))) { 76 | co_return; 77 | } 78 | 79 | std::cout << "connected\n"; 80 | char message[] = "hello, world\n"; 81 | auto b = net::buffer(message); 82 | if (0 < co_await net::async_send(client, b)) { 83 | char buffer[20]; 84 | while (auto size = co_await net::async_receive(client, net::buffer(buffer))) { 85 | std::string_view response(buffer, size); 86 | std::cout << "received='" << response << "'\n"; 87 | // if (response.find('\n') != response.npos) 88 | // break; 89 | } 90 | } 91 | }, 92 | context) 93 | #if 0 94 | | ex::upon_error([](std::exception_ptr ex) { 95 | try { 96 | std::cout << "encountered an error!\n"; 97 | std::rethrow_exception(ex); 98 | } 99 | catch (std::system_error const& error) { 100 | std::cout << "error=" << error.what() << "\n"; 101 | } 102 | catch (...) 103 | { 104 | std::cout << "unknown error\n"; 105 | } 106 | }) 107 | #endif 108 | ); 109 | 110 | context.run(); 111 | } 112 | -------------------------------------------------------------------------------- /examples/cppcon-2024.cpp: -------------------------------------------------------------------------------- 1 | // examples/http-server.cpp -*-C++-*- 2 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | #include 5 | #include 6 | #include "demo_algorithm.hpp" 7 | #include "demo_error.hpp" 8 | #include "demo_scope.hpp" 9 | #include "demo_task.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace ex = beman::execution; 18 | namespace net = beman::net; 19 | using namespace std::chrono_literals; 20 | 21 | // ---------------------------------------------------------------------------- 22 | 23 | std::unordered_map files{ 24 | {"/", "examples/data/index.html"}, 25 | {"/favicon.ico", "examples/data/favicon.ico"}, 26 | {"/logo.png", "examples/data/logo.png"}, 27 | }; 28 | 29 | auto process(auto& stream, const auto& request) -> demo::task<> { 30 | std::cout << "request=" << request << "\n"; 31 | std::string method, url, version; 32 | std::string body; 33 | std::ostringstream out; 34 | if (std::istringstream(request) >> method >> url >> version && files.contains(url)) { 35 | std::cout << "url=" << url << "\n"; 36 | out << std::ifstream(files[url]).rdbuf(); 37 | body = out.str(); 38 | out.str({}); 39 | } 40 | 41 | out << "HTTP/1.1 " << (body.empty() ? "404 not found" : "200 found") << "\r\n" 42 | << "Content-Length: " << body.size() << "\r\n" 43 | << "\r\n" 44 | << body; 45 | auto response{out.str()}; 46 | co_await net::async_send(stream, net::buffer(response)); 47 | } 48 | 49 | auto timeout(auto scheduler, auto duration, auto sender) { 50 | return demo::when_any(std::move(sender), net::resume_after(scheduler, duration) | demo::into_error([] { 51 | return std::error_code(demo::timeout, demo::category()); 52 | })); 53 | } 54 | 55 | auto make_client_handler(auto scheduler, auto stream) -> demo::task<> { 56 | char buffer[16]; 57 | std::string request; 58 | while (true) 59 | try { 60 | if (auto n = co_await timeout(scheduler, 2s, net::async_receive(stream, net::buffer(buffer)))) { 61 | std::string_view data(buffer, n); 62 | request += data; 63 | if (request.find("\r\n\r\n") != request.npos) { 64 | co_await process(stream, request); 65 | break; 66 | } 67 | } else { 68 | // std::cout << "ERROR (via expected): " << std::get<0>(n.error()).message() << "\n"; 69 | break; 70 | } 71 | } catch (const std::variant& ex) { 72 | std::cout << "ERROR: " << std::get<0>(ex).message() << "\n"; 73 | break; 74 | } 75 | 76 | co_return; 77 | } 78 | 79 | auto main() -> int { 80 | demo::scope scope; 81 | 82 | net::io_context context; 83 | net::ip::tcp::endpoint endpoint(net::ip::address_v4::any(), 12345); 84 | net::ip::tcp::acceptor acceptor(context, endpoint); 85 | 86 | scope.spawn(std::invoke( 87 | [](auto scheduler, auto& scp, auto& acc) -> demo::task<> { 88 | while (true) { 89 | auto [stream, address] = co_await net::async_accept(acc); 90 | std::cout << "received client: " << address << "\n"; 91 | scp.spawn(make_client_handler(scheduler, std::move(stream))); 92 | } 93 | }, 94 | context.get_scheduler(), 95 | scope, 96 | acceptor)); 97 | 98 | context.run(); 99 | } 100 | -------------------------------------------------------------------------------- /examples/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bemanproject/net/193d043002143242731f9baf759efc6d624cace7/examples/data/favicon.ico -------------------------------------------------------------------------------- /examples/data/index-milano.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ciao Milano! 4 | 5 | 6 | 7 |

Ciao Milano!

8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello CppCon 4 | 5 | 6 | 7 |

Hello CppCon!

8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/data/itcpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bemanproject/net/193d043002143242731f9baf759efc6d624cace7/examples/data/itcpp.png -------------------------------------------------------------------------------- /examples/data/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bemanproject/net/193d043002143242731f9baf759efc6d624cace7/examples/data/logo.png -------------------------------------------------------------------------------- /examples/demo_algorithm.hpp: -------------------------------------------------------------------------------- 1 | // examples/demo_algorithm.hpp -*-C++-*- 2 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 3 | 4 | #ifndef INCLUDED_EXAMPLES_DEMO_ALGORITHM 5 | #define INCLUDED_EXAMPLES_DEMO_ALGORITHM 6 | 7 | #if defined(__GNUC__) 8 | #pragma GCC diagnostic push 9 | #pragma GCC diagnostic ignored "-Wmissing-braces" 10 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 11 | #endif 12 | 13 | #if defined(__clang__) 14 | #pragma clang diagnostic push 15 | #pragma clang diagnostic ignored "-Wunknown-warning-option" 16 | #pragma clang diagnostic ignored "-Wmissing-braces" 17 | #endif 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #if 202202L <= __cpp_lib_expected 28 | #include 29 | #endif 30 | 31 | // ---------------------------------------------------------------------------- 32 | 33 | namespace demo { 34 | namespace ex = ::beman::net::detail::ex; 35 | } 36 | 37 | namespace demo::detail { 38 | template 39 | struct into_error_transform_helper { 40 | using type = T; 41 | }; 42 | template 43 | struct into_error_transform_helper { 44 | using type = ex::set_error_t(decltype(::std::declval()(::std::declval()...))); 45 | }; 46 | template 47 | struct into_error_transform { 48 | template 49 | using type = typename into_error_transform_helper::type; 50 | }; 51 | 52 | template 53 | struct variant_from_list; 54 | template 55 | struct variant_from_list> { 56 | using type = ex::detail::variant_or_empty; 57 | }; 58 | template 59 | struct variant_from_list> { 60 | using type = ex::detail::variant_or_empty; 61 | }; 62 | template 63 | using variant_from_list_t = typename variant_from_list::type; 64 | 65 | template 66 | struct is_set_error { 67 | static constexpr bool value{false}; 68 | }; 69 | template 70 | struct is_set_error { 71 | static constexpr bool value{true}; 72 | }; 73 | 74 | template 75 | struct is_set_value { 76 | static constexpr bool value{false}; 77 | }; 78 | template 79 | struct is_set_value { 80 | static constexpr bool value{true}; 81 | }; 82 | 83 | template 84 | struct decayed_set_value; 85 | template 86 | struct decayed_set_value { 87 | using type = ::std::tuple<::std::decay_t...>; 88 | }; 89 | template 90 | using decayed_set_value_t = typename decayed_set_value::type; 91 | 92 | template 93 | struct decayed_tuple_or_single { 94 | using type = ::std::tuple<::std::decay_t...>; 95 | }; 96 | template 97 | struct decayed_tuple_or_single { 98 | using type = ::std::decay_t; 99 | }; 100 | template 101 | using decayed_tuple_or_single_t = typename decayed_tuple_or_single::type; 102 | 103 | template 104 | struct make_type_list; 105 | template