Compare commits
321 Commits
enviroment
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
205868a868 | ||
|
1632ef74af | ||
|
ee9cd987e7 | ||
|
4ef724041b | ||
|
943b065626 | ||
|
719e8d4f26 | ||
|
92e5c3169c | ||
|
a2d8f28cd1 | ||
|
20a6779e2f | ||
|
c0f021e57f | ||
|
d351b49148 | ||
|
4dccde7830 | ||
|
ff58e6506d | ||
|
2d61896824 | ||
|
e26474a2d7 | ||
|
280d6bda3c | ||
|
a7ed7a0d65 | ||
|
83ede4ef81 | ||
|
aaf6e6ec0c | ||
|
deabd1865a | ||
|
25b446a5cc | ||
|
253e9f9700 | ||
|
ddad9eafba | ||
|
a03d22ce8d | ||
|
a2149aa4ce | ||
|
9f57bbaecd | ||
|
243c49234f | ||
|
588e15a8b6 | ||
|
88f8fa7d75 | ||
|
2b10ef61d0 | ||
|
860a302219 | ||
|
23fe33abce | ||
|
8d86dde405 | ||
|
99f89c2e8b | ||
|
4178308e96 | ||
|
e008a45cf7 | ||
|
8c4aecf6e0 | ||
|
87cea02b45 | ||
|
8fbeaea80d | ||
|
0b8fd86680 | ||
|
f33627d05a | ||
|
dcf160f017 | ||
|
ef80bd0c5f | ||
|
aec2f3f496 | ||
|
b39e1c4a0f | ||
|
d85c29427d | ||
|
c8b8adca5d | ||
|
986545b2ec | ||
|
ad95299a7e | ||
|
93a15a3cf8 | ||
|
c61b5c7e93 | ||
|
0b14f0c563 | ||
|
fc95405a06 | ||
|
d7c26e5858 | ||
|
bda1e503c7 | ||
|
b51088a9f0 | ||
|
2630dff5ac | ||
|
7f73f3dcad | ||
|
a32bfa24d3 | ||
|
a6b54d231d | ||
|
4fc3ef5208 | ||
a92cffd150 | |||
|
b94c7465c6 | ||
|
21431af191 | ||
|
de210b571d | ||
|
e101d362b9 | ||
|
e46a41d2ff | ||
|
a262a643e9 | ||
|
268455532b | ||
|
89b3519c24 | ||
|
7aecf2ea19 | ||
|
609ddf1854 | ||
|
1a7fdf06cc | ||
|
79da98e058 | ||
|
e4b211b21a | ||
|
fa853e000f | ||
|
bfbc82d6a5 | ||
|
0e515c727b | ||
|
4990e4ff1f | ||
|
b38db9fdaa | ||
|
6a3308fc46 | ||
|
d4c3dbb280 | ||
|
e4797d08e1 | ||
|
02740d5865 | ||
|
baabdd2655 | ||
f57fc87673 | |||
|
5f0f511066 | ||
|
b612209914 | ||
|
0529a84fb7 | ||
|
8cda4f4d8e | ||
|
fe6c1e3bd0 | ||
|
b924f7dff2 | ||
|
f10eb5c2ad | ||
|
7621e6e3ff | ||
|
2a3bfa14ae | ||
|
6c631dc075 | ||
|
346c66a8f4 | ||
|
2ac95e3b14 | ||
480de4182c | |||
|
8348a857f3 | ||
|
e9d67178da | ||
|
0d7f4b1eb5 | ||
|
b93a236e37 | ||
|
78b1e7d703 | ||
|
cfa0513226 | ||
|
d784da1e8d | ||
|
145441cead | ||
|
5866278340 | ||
|
e8ef207ec9 | ||
|
ecabf885f3 | ||
|
0ee52951c1 | ||
|
32f2183136 | ||
|
57ac46cf9b | ||
|
6389535443 | ||
|
b6b1209014 | ||
|
20bf379332 | ||
|
95c296a332 | ||
|
68f5298e39 | ||
|
225befb22b | ||
|
bc5736bf35 | ||
|
548b29d897 | ||
|
5a7c204ceb | ||
|
6a98178690 | ||
|
ceeb25ea82 | ||
|
6a71614cab | ||
|
038de0fc27 | ||
|
d9c0468729 | ||
|
857f8f3b52 | ||
|
973fbd62f7 | ||
|
9fb1815e01 | ||
|
9a978d8984 | ||
|
e7ec8229e1 | ||
|
f42e700747 | ||
|
34eb56ac50 | ||
|
1384e5f96e | ||
|
3ed11fd33b | ||
|
8f46d49bac | ||
|
5ad87f4a91 | ||
|
57e3ee06dd | ||
|
f900647c76 | ||
|
bd116d8810 | ||
|
691d4d84ac | ||
|
a8ee488010 | ||
|
ae5a9294eb | ||
|
5589094034 | ||
|
07317e19eb | ||
|
1b88afa283 | ||
|
4c592091da | ||
|
5612b7256a | ||
|
c6061d07bc | ||
|
893d20cee1 | ||
|
a217a09aec | ||
|
829243f059 | ||
|
2f101fdccf | ||
|
ddf9cc8f8c | ||
|
e57a60c36f | ||
|
7665ea0b53 | ||
|
676f41909f | ||
|
98a88c3acc | ||
|
cb13dc9591 | ||
|
fefde2f12e | ||
|
eb4bf1c270 | ||
|
96c96ef2b0 | ||
|
9b846d8115 | ||
|
b4984d5c61 | ||
|
9956cf8993 | ||
|
b1bed2c7da | ||
|
4209a495ea | ||
|
9213d5219a | ||
|
0743a9b7c4 | ||
|
91f401a13a | ||
|
d77f844c81 | ||
|
ab0ba8d4c8 | ||
|
eb822a4a6e | ||
|
de92564cc1 | ||
|
497a4bcc6a | ||
|
421f8111f0 | ||
|
aabcc42625 | ||
|
f2a78cd331 | ||
|
1597b678e1 | ||
|
3b1500313c | ||
|
00b11087b4 | ||
|
c0af952fc6 | ||
|
7b5e43293a | ||
|
1fa2ec6b76 | ||
|
2b29522293 | ||
|
b8feb4043e | ||
|
5c53bb9e9f | ||
|
43555cbc1c | ||
|
cb5eedb2a5 | ||
|
183907a0ed | ||
|
99482d4c7c | ||
|
b9eb3f957d | ||
|
5c47b7b808 | ||
|
2452b95a90 | ||
|
e3164395de | ||
|
da1ac0dcf7 | ||
|
617fbac98f | ||
|
eb36ad2c93 | ||
|
ab6ed8f45c | ||
|
b06ad84514 | ||
|
e16a28dfdc | ||
|
7fb6df219c | ||
|
0b3dc2bb57 | ||
|
81f512d69d | ||
|
831de5abe5 | ||
|
a3d0a942e4 | ||
|
e090778db9 | ||
|
881dc8975a | ||
|
75c9eefd50 | ||
|
d8f8214556 | ||
|
0e796d5efc | ||
2ea507dde2 | |||
4a844a319e | |||
4d272723c7 | |||
|
7b572e2a1f | ||
|
24b1a71e55 | ||
|
742b48e1ce | ||
772686a2fc | |||
21bf18bbdd | |||
d60e2dfb38 | |||
ea1dddaf26 | |||
854b72cf35 | |||
29f9a4467c | |||
2dd97709a0 | |||
ed3b2006e9 | |||
387835a155 | |||
7a3d211d09 | |||
bf3f388acb | |||
09f736bf83 | |||
16d1a5e0d6 | |||
910792e383 | |||
55554606a1 | |||
5ab750b93b | |||
7d0f732a57 | |||
e6aed50fe9 | |||
b930ef4e6e | |||
b7d879bf70 | |||
d16f6de53c | |||
91eaa0ceea | |||
118837f6d8 | |||
e528fd9e83 | |||
7c5f3e2170 | |||
c1e1acd6e2 | |||
4d88ca7e40 | |||
946d4b96b1 | |||
45a3710626 | |||
1e1d9b0cb6 | |||
0a00080d2d | |||
23a230c9d3 | |||
31dfcc37ca | |||
43d7aeac1d | |||
ada8e17d1b | |||
2eee11e476 | |||
25e730c8d3 | |||
016e48570e | |||
3c4da4a226 | |||
96378a16c1 | |||
9c4b57f217 | |||
605533de32 | |||
df236b13c8 | |||
4985843f8f | |||
a665d95692 | |||
dc1322e4ea | |||
563786312c | |||
26521be98d | |||
fd63beab86 | |||
3caa5b80cb | |||
7cc61e30e4 | |||
ad79c17551 | |||
741eb7f576 | |||
e2142d9dbd | |||
70e1431f05 | |||
5d410a1ffd | |||
4421acebd6 | |||
611007a888 | |||
80bc4c039c | |||
6611512b1f | |||
64417bf187 | |||
d549d23f0a | |||
15f5e66e0b | |||
fd6009bb02 | |||
fe2cd9f1ef | |||
6652a08f42 | |||
d1366aee74 | |||
b422ca8677 | |||
1c6db5e7b7 | |||
2c19db7354 | |||
5560549c7c | |||
ba463139d6 | |||
2e2c34ce21 | |||
142680ab77 | |||
7d2ba379f7 | |||
3c476d4629 | |||
0a024430e8 | |||
61cf0559b1 | |||
8853451cb5 | |||
f28cb10669 | |||
23b9d901ac | |||
045150938c | |||
|
201f4c4cf8 | ||
|
f39296ae22 | ||
|
d249386030 | ||
|
da5964a778 | ||
|
873941110a | ||
0ce1b59757 | |||
b193ca1213 | |||
9ed25cc32c | |||
2c9792d6b8 | |||
601659399c | |||
794502188b | |||
9e2784f609 | |||
10d1223f9f | |||
bde30f5d99 | |||
de1ed62f6b | |||
5b3cfca2a8 | |||
c1493a75c2 | |||
6bc2a1cd38 | |||
8ac9fc5929 | |||
b9d87e1456 | |||
d542bbe696 |
8
.gitignore
vendored
8
.gitignore
vendored
@ -5,3 +5,11 @@ coverage
|
|||||||
doc/musique
|
doc/musique
|
||||||
doc/build
|
doc/build
|
||||||
doc/source/api
|
doc/source/api
|
||||||
|
doc/*.html
|
||||||
|
doc/*.pdf
|
||||||
|
__pycache__
|
||||||
|
drafts.cc
|
||||||
|
.cache
|
||||||
|
release_*
|
||||||
|
*.zip
|
||||||
|
*.html
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
image: gcc
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- build
|
|
||||||
- test
|
|
||||||
|
|
||||||
build:
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- make
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- main
|
|
||||||
stage: test
|
|
||||||
|
|
||||||
unit-testing:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- make unit-tests
|
|
144
CHANGELOG.md
Normal file
144
CHANGELOG.md
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.5.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Builtin documentation for builtin functions display from repl and command line (`musique doc <builtin>`)
|
||||||
|
- Man documentation for commandline interface builtin (`musique man`)
|
||||||
|
- Suggestions which command line parameters user may wanted to use
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Moved from `bestline` to `replxx` Readline implementation due to lack of Windows support from bestline
|
||||||
|
- New parameter passing convention for command line invocation. `musique help` to learn how it changed
|
||||||
|
- `CTRL-C` handler that turns notes that are playing off
|
||||||
|
|
||||||
|
## [0.4.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Builtin function documentation generation from C++ Musique implementation source code
|
||||||
|
- New builtins: digits
|
||||||
|
- Negative numbers!
|
||||||
|
- Version command via `:version` in REPL or `--version`, `-v` in command line.
|
||||||
|
- Introduced start synchronization with builtins: `peers` and `start`
|
||||||
|
- Connection with MIDI ports via parameters dropped in favour of function using context system: `port`
|
||||||
|
- Listing ports via REPL command: `:ports` instead of commandline parameter
|
||||||
|
- Building release with `make musique.zip` using Docker
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Readme from Polish to English
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Release script builder
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `ceil`, `round`, `floor` didn't behave well with negative numbers
|
||||||
|
- `duration` wasn't filling note length from context and summed all notes inside chord, when it should take max
|
||||||
|
- `try` evaluated arguments too quickly
|
||||||
|
- Nested arithmetic expression with undefined operator reports proper error and don't crash
|
||||||
|
|
||||||
|
## [0.3.1]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- release build script was producing executable with wrong path
|
||||||
|
- `examples/for-elise.mq` had bug in it
|
||||||
|
- in error reporting printing garbage instead of function name was fixed
|
||||||
|
- sending proper program change message
|
||||||
|
|
||||||
|
## [0.3.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- new builtins: map, while, set_len, set_oct, duration, pick
|
||||||
|
- `<note><octave>` notation like `c4` that mimics [scientific notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation)
|
||||||
|
- operator pretty printing while printing values
|
||||||
|
- macros: builtin functions that takes AST and produces value
|
||||||
|
- early text-based snapshot system available via `:snap` command inside interactive session
|
||||||
|
- polish basic tutorial
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Block can be called with more parameters then it requires
|
||||||
|
- reorganized fold argument order
|
||||||
|
- Moved from `(<note> <octave> <length>)` invocation to `(<note> <length>)`
|
||||||
|
- Moved from '[]' to '()' notation for blocks
|
||||||
|
- Moved from `a.n` index operator to `a[n]`
|
||||||
|
- Moved from ';' to ',' notation for expression separator
|
||||||
|
- Moved 'if', 'while' from beeing functions to macros - side effect of new notation
|
||||||
|
- Build system uses now Docker
|
||||||
|
- Array repetition using `number * array` like `3 * (c, e) == (c, e, c, e, c, e)`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Index operation using booleans behaves like a mask and not fancy way of spelling 0 and 1
|
||||||
|
- Blocks are check against beeing a collection at runtime to prevent treating anonymous functions as collections and cousing assertions
|
||||||
|
- On Windows default terminal emulator ansi escape codes are conditionally supported. Review musique/pretty.cc for details
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed `<note><absolute notes indexes>` chord notation like `c47` meaning c-major
|
||||||
|
- Removed obsolete documentation
|
||||||
|
- `h` as note literal
|
||||||
|
|
||||||
|
## [0.2.1] - 2022-10-21
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Windows build doesn't require pthread dll
|
||||||
|
|
||||||
|
## [0.2.0] - 2022-10-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added `scan` builtin, which computes prefix sum of passed values when provided with addition operator
|
||||||
|
* Added [rtmidi](https://github.com/thestk/rtmidi/) dependency which should provide multiplatform MIDI support
|
||||||
|
* Support for Windows (with only basic REPL) (`make os=windows`)
|
||||||
|
* Support for MacOS (`make os=macos`)
|
||||||
|
* Release package now with compiled Windows binary
|
||||||
|
* `:load` REPL command to load Musique files inside Musique session. Allows for delayed file execution after a connection
|
||||||
|
* `:quit` REPL command that mirrors `:exit` command
|
||||||
|
* Virtual MIDI output port creation as default action (--output connects to existing one)
|
||||||
|
* Added build instructions
|
||||||
|
* `-f` commandline argument that will turn file into deffered function
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Integrated libmidi library into Musique codebase
|
||||||
|
* Moved from custom ALSA interaction to using rtmidi for MIDI I/O operations
|
||||||
|
* VSCode extension has been re-created
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* Support for incoming MIDI messages handling due to poor implementation that didn't statisfy user needs
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Prevented accidental recursive construction of Arrays and Values by making convinience constructor `Value::Value(std::vector<Value>&&)` explicit
|
||||||
|
|
||||||
|
## [0.1.0] - 2022-09-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Musique programming language initial implementation that supports:
|
||||||
|
* Chord system
|
||||||
|
* Playing MIDI notes using par, sim and play
|
||||||
|
* Notes and chords as first-class citizens of Musique
|
||||||
|
* Bunch of builtins like math and array operations
|
||||||
|
* All numerical values as fractions (like in JavaScript but better)
|
||||||
|
* Primitive interactive mode
|
||||||
|
* Only ALSA MIDI Sequencer output
|
||||||
|
* Simple regression testing framework
|
||||||
|
* Basic documentation of builtin functions and operators
|
43
Dockerfile
Normal file
43
Dockerfile
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
FROM ubuntu:20.04 AS linux
|
||||||
|
ARG TZ=Europe/Warsaw
|
||||||
|
ARG VERSION
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
RUN apt update && apt install -y make software-properties-common zip unzip git
|
||||||
|
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||||
|
RUN apt install -y gcc-11 g++-11 libasound2-dev
|
||||||
|
RUN mkdir -p /src/
|
||||||
|
WORKDIR /src/
|
||||||
|
COPY config.mk Makefile /src/
|
||||||
|
COPY .git /src/.git/
|
||||||
|
COPY musique /src/musique/
|
||||||
|
COPY lib /src/lib/
|
||||||
|
COPY scripts /src/scripts/
|
||||||
|
RUN make clean && make CC=gcc-11 CXX=g++-11 VERSION="$VERSION"
|
||||||
|
|
||||||
|
|
||||||
|
FROM ubuntu:22.04 AS windows
|
||||||
|
ARG VERSION
|
||||||
|
RUN apt update && apt install -y git make gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64
|
||||||
|
RUN mkdir -p /src/
|
||||||
|
WORKDIR /src/
|
||||||
|
COPY config.mk Makefile /src/
|
||||||
|
COPY .git /src/.git/
|
||||||
|
COPY musique /src/musique/
|
||||||
|
COPY lib /src/lib/
|
||||||
|
COPY scripts /src/scripts/
|
||||||
|
RUN make clean && make os=windows CC=x86_64-w64-mingw32-gcc-posix CXX=x86_64-w64-mingw32-g++-posix VERSION="$VERSION"
|
||||||
|
|
||||||
|
|
||||||
|
FROM ubuntu:22.04 AS release
|
||||||
|
RUN apt update && apt install -y zip pandoc python3 python-is-python3 pandoc
|
||||||
|
COPY CHANGELOG.md LICENSE /musique/
|
||||||
|
COPY examples /musique/examples/
|
||||||
|
COPY --from=windows /src/bin/musique.exe /musique/musique-windows.exe
|
||||||
|
COPY --from=linux /src/bin/musique /musique/musique-linux
|
||||||
|
|
||||||
|
COPY doc /doc/
|
||||||
|
COPY scripts /scripts/
|
||||||
|
RUN python /scripts/language-cmp-cheatsheet.py /doc/musique-vs-languages-cheatsheet.template \
|
||||||
|
&& bash -c 'cp /{doc,musique}/musique-vs-languages-cheatsheet.html'
|
||||||
|
RUN pandoc -o /musique/wprowadzenie.html /doc/wprowadzenie.md -s --toc
|
||||||
|
RUN zip -r musique.zip /musique/
|
16
Doxyfile
16
Doxyfile
@ -58,7 +58,7 @@ PROJECT_LOGO =
|
|||||||
# entered, it will be relative to the location where doxygen was started. If
|
# entered, it will be relative to the location where doxygen was started. If
|
||||||
# left blank the current directory will be used.
|
# left blank the current directory will be used.
|
||||||
|
|
||||||
OUTPUT_DIRECTORY = doc/build/doxygen/
|
OUTPUT_DIRECTORY = doc/build/
|
||||||
|
|
||||||
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
|
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
|
||||||
# directories (in 2 levels) under the output directory of each output format and
|
# directories (in 2 levels) under the output directory of each output format and
|
||||||
@ -485,13 +485,13 @@ NUM_PROC_THREADS = 1
|
|||||||
# normally produced when WARNINGS is set to YES.
|
# normally produced when WARNINGS is set to YES.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_ALL = NO
|
EXTRACT_ALL = YES
|
||||||
|
|
||||||
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
||||||
# be included in the documentation.
|
# be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
EXTRACT_PRIVATE = YES
|
||||||
|
|
||||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||||
# methods of a class will be included in the documentation.
|
# methods of a class will be included in the documentation.
|
||||||
@ -864,7 +864,7 @@ WARN_LOGFILE =
|
|||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = src
|
INPUT = musique doc/index.md
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@ -952,7 +952,7 @@ RECURSIVE = YES
|
|||||||
# Note that relative paths are relative to the directory from which doxygen is
|
# Note that relative paths are relative to the directory from which doxygen is
|
||||||
# run.
|
# run.
|
||||||
|
|
||||||
EXCLUDE = tests
|
EXCLUDE = tests src/main.cc
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||||
@ -1061,7 +1061,7 @@ FILTER_SOURCE_PATTERNS =
|
|||||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||||
# and want to reuse the introduction page also for the doxygen output.
|
# and want to reuse the introduction page also for the doxygen output.
|
||||||
|
|
||||||
USE_MDFILE_AS_MAINPAGE =
|
USE_MDFILE_AS_MAINPAGE = doc/index.md
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to source browsing
|
# Configuration options related to source browsing
|
||||||
@ -1213,7 +1213,7 @@ IGNORE_PREFIX =
|
|||||||
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
GENERATE_HTML = NO
|
GENERATE_HTML = YES
|
||||||
|
|
||||||
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
|
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
|
||||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||||
@ -1582,7 +1582,7 @@ DISABLE_INDEX = NO
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
GENERATE_TREEVIEW = NO
|
GENERATE_TREEVIEW = YES
|
||||||
|
|
||||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||||
# doxygen will group on one line in the generated HTML documentation.
|
# doxygen will group on one line in the generated HTML documentation.
|
||||||
|
661
LICENSE
Normal file
661
LICENSE
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
Musique
|
||||||
|
Copyright (C) 2022 Projekt inżynierski
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
98
Makefile
98
Makefile
@ -1,71 +1,55 @@
|
|||||||
MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
|
include config.mk
|
||||||
CXXFLAGS:=$(CXXFLAGS) -std=c++20 -Wall -Wextra -Werror=switch -Werror=return-type -Werror=unused-result
|
|
||||||
CPPFLAGS:=$(CPPFLAGS) -Ilib/expected/ -Ilib/ut/ -Isrc/
|
|
||||||
RELEASE_FLAGS=-O3
|
|
||||||
DEBUG_FLAGS=-O0 -ggdb
|
|
||||||
|
|
||||||
Obj= \
|
Sources := $(shell find musique/ -name '*.cc')
|
||||||
environment.o \
|
Obj := $(subst musique/,,$(Sources:%.cc=%.o))
|
||||||
errors.o \
|
|
||||||
interpreter.o \
|
|
||||||
lexer.o \
|
|
||||||
location.o \
|
|
||||||
number.o \
|
|
||||||
parser.o \
|
|
||||||
unicode.o \
|
|
||||||
unicode_tables.o \
|
|
||||||
value.o
|
|
||||||
|
|
||||||
Release_Obj=$(addprefix bin/,$(Obj))
|
ifeq ($(os),windows)
|
||||||
Debug_Obj=$(addprefix bin/debug/,$(Obj))
|
all: bin/musique.exe
|
||||||
|
debug: bin/windows/debug/musique.exe
|
||||||
|
else
|
||||||
|
all: bin/musique
|
||||||
|
debug: bin/$(os)/debug/musique
|
||||||
|
endif
|
||||||
|
|
||||||
all: bin/musique bin/unit-tests
|
include scripts/$(os).mk
|
||||||
|
include scripts/build.mk
|
||||||
|
include scripts/test.mk
|
||||||
|
|
||||||
debug: bin/debug/musique
|
bin/$(Target): bin/$(os)/$(Target)
|
||||||
|
ln -f $< $@
|
||||||
|
|
||||||
bin/%.o: src/%.cc src/*.hh
|
doc: Doxyfile musique/*.cc musique/*.hh
|
||||||
g++ $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c
|
|
||||||
|
|
||||||
bin/musique: $(Release_Obj) bin/main.o src/*.hh
|
|
||||||
g++ $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $(Release_Obj) bin/main.o
|
|
||||||
|
|
||||||
bin/debug/musique: $(Debug_Obj) bin/debug/main.o src/*.hh
|
|
||||||
g++ $(CXXFLAGS) $(DEBUG_FLAGS) $(CPPFLAGS) -o $@ $(Debug_Obj) bin/debug/main.o
|
|
||||||
|
|
||||||
bin/debug/%.o: src/%.cc src/*.hh
|
|
||||||
g++ $(CXXFLAGS) $(DEBUG_FLAGS) $(CPPFLAGS) -o $@ $< -c
|
|
||||||
|
|
||||||
.PHONY: unit-tests
|
|
||||||
unit-tests: bin/unit-tests
|
|
||||||
./$<
|
|
||||||
|
|
||||||
.PHONY: unit-test-coverage
|
|
||||||
unit-test-coverage:
|
|
||||||
@which gcov >/dev/null || ( echo "[ERROR] gcov is required for test coverage report"; false )
|
|
||||||
@which gcovr >/dev/null || ( echo "[ERROR] gcovr is required for test coverage report"; false )
|
|
||||||
CXXFLAGS=--coverage $(MAKE) bin/unit-tests -B
|
|
||||||
bin/unit-tests
|
|
||||||
rm -rf coverage
|
|
||||||
mkdir coverage
|
|
||||||
gcovr -e '.*\.hpp' --html --html-details -o coverage/index.html
|
|
||||||
rm -rf bin
|
|
||||||
xdg-open coverage/index.html
|
|
||||||
|
|
||||||
.PHONY: doc
|
|
||||||
doc: Doxyfile src/*.cc src/*.hh
|
|
||||||
doxygen
|
doxygen
|
||||||
cd doc; $(MAKE) html
|
|
||||||
|
|
||||||
.PHONY: doc-open
|
|
||||||
doc-open: doc
|
doc-open: doc
|
||||||
xdg-open ./doc/build/html/index.html
|
xdg-open ./doc/build/html/index.html
|
||||||
|
|
||||||
bin/unit-tests: src/tests/*.cc $(Release_Obj)
|
|
||||||
g++ $(CXXFLAGS) $(CPPFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin coverage
|
rm -rf bin coverage
|
||||||
|
|
||||||
.PHONY: clean
|
release: bin/musique
|
||||||
|
scripts/release
|
||||||
|
|
||||||
$(shell mkdir -p bin/debug)
|
install: bin/musique
|
||||||
|
scripts/install
|
||||||
|
|
||||||
|
doc/musique-vs-languages-cheatsheet.html: doc/musique-vs-languages-cheatsheet.template
|
||||||
|
scripts/language-cmp-cheatsheet.py $<
|
||||||
|
|
||||||
|
doc/wprowadzenie.html: doc/wprowadzenie.md
|
||||||
|
pandoc -o $@ $< -s --toc
|
||||||
|
|
||||||
|
doc/functions.html: musique/interpreter/builtin_functions.cc scripts/document-builtin.py
|
||||||
|
scripts/document-builtin.py -o $@ $<
|
||||||
|
|
||||||
|
musique.zip:
|
||||||
|
docker build -t musique-builder --build-arg "VERSION=$(VERSION)" .
|
||||||
|
docker create --name musique musique-builder
|
||||||
|
docker cp musique:/musique.zip musique.zip
|
||||||
|
docker rm -f musique
|
||||||
|
|
||||||
|
.PHONY: clean doc doc-open all test unit-tests release install musique.zip
|
||||||
|
|
||||||
|
$(shell mkdir -p $(subst musique/,bin/$(os)/,$(shell find musique/* -type d)))
|
||||||
|
$(shell mkdir -p bin/$(os)/replxx/)
|
||||||
|
$(shell mkdir -p $(subst musique/,bin/$(os)/debug/,$(shell find musique/* -type d)))
|
||||||
|
53
README.md
53
README.md
@ -1,37 +1,36 @@
|
|||||||
# Musique interpreter
|
# Musique interpreter
|
||||||
|
|
||||||
Interpreter języka Musique. Możliwy do wykorzystywania jako:
|
Reference implementation of Musique programming language.
|
||||||
|
|
||||||
- biblioteka interpretera języka dołączana do innego projektu (podobnie jak Lua);
|
## Building
|
||||||
- REPL działający w systemie GNU/Linux + ALSA wykonujący język Musique.
|
|
||||||
|
|
||||||
## Dostępne komendy
|
Reference [`build_instructions.md`](./build_instructions.md).
|
||||||
|
|
||||||
- `make` - Buduje interpreter `bin/musique` (tryb release)
|
## Syntax highlighting
|
||||||
- `make debug` - Buduje interpreter `bin/debug/musique` (tryb debug)
|
|
||||||
- `make clean` - Usuwa reprodukowalne elementy projektu (automatycznie stworzone pliki binarne czy raporty)
|
|
||||||
|
|
||||||
### Dokumentacja
|
### Vim / Neovim
|
||||||
|
|
||||||
- `make doc` - Tworzy `doc/build/html/` zawierający dokumentację projektu
|
Copy [editor/musique.vim](editor/musique.vim) to `syntax` directory inside your Vim (Neovim) configuration.
|
||||||
|
|
||||||
### Testowanie
|
|
||||||
|
|
||||||
- `make unit-tests` - Uruchamia testy jednostkowe interpretera
|
|
||||||
- `make unit-test-coverage` - Uruchamia raport pokrycia kodu przez testy jednostkowe
|
|
||||||
|
|
||||||
## Budowa projektu
|
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ cp editor/musique.vim ~/.config/nvim/syntax/
|
||||||
```
|
```
|
||||||
.
|
|
||||||
├── bin Miejsce produkcji plików wykonywalnych
|
Next, you can add bindings for filetype:
|
||||||
├── coverage
|
|
||||||
├── doc Dokumentacja języka, interpretera
|
```vim
|
||||||
│ ├── build Miejsce produkcji dokumentacji
|
au BufRead,BufNewFile *.mq set filetype=musique
|
||||||
│ └── source Źródła dokumentacji Sphinx
|
|
||||||
├── lib Zewnętrzne zależności projektu
|
|
||||||
│ ├── expected
|
|
||||||
│ └── ut
|
|
||||||
└── src Główny katalog z kodem źródłowym
|
|
||||||
└── tests Katalog z testami jednostkowymi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Visual Studio Code
|
||||||
|
|
||||||
|
Copy [editor/vscode-musique](editor/vscode-musique) directory to `<user home>/.vscode/extensions` and restart VS Code.
|
||||||
|
|
||||||
|
# Thanks to
|
||||||
|
|
||||||
|
- Creator of [tl::expected](https://github.com/TartanLlama/expected) - [Sy Brand](https://sybrand.ink/)
|
||||||
|
- Creator of [bestline](https://github.com/jart/bestline) - [Justine Tunney](https://justinetunney.com/)
|
||||||
|
- Creator of [rtmidi](https://github.com/thestk/rtmidi/) - [Gary P. Scavone](http://www.music.mcgill.ca/~gary/)
|
||||||
|
- Creators of [link](https://github.com/Ableton/link)
|
||||||
|
|
||||||
|
and all contributors that created libraries above.
|
||||||
|
27
build_instructions.md
Normal file
27
build_instructions.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Musique build instructions
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
|
||||||
|
Use your local C++ compiler (supporting C++20) and ALSA dev libraries or included Dockerfile.
|
||||||
|
|
||||||
|
## MacOS
|
||||||
|
|
||||||
|
Required system dependency is fairly new C++ compiler. The simplest way is to type `clang` in terminal, which should launch installation of C++ compiler. Next provided compiler version:
|
||||||
|
```
|
||||||
|
$ clang++ --version
|
||||||
|
```
|
||||||
|
|
||||||
|
Minimal supported version is __14__. On older editions of MacOS one can aquire new editions by [Homebrew](https://brew.sh/). After homebrew installation install clang via `brew install llvm`.
|
||||||
|
|
||||||
|
Next you should be able to build project by running `make` command inside main directory (in released zip file in `source_code` directory).
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
Windows support is provided via cross compilation. Mingw GCC C++ compiler is required to produce Windows binaries.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make os=windows
|
||||||
|
```
|
||||||
|
|
||||||
|
will create `bin/musique.exe` that can be used on x86_64 Windows operating systems or use included Dockerfile
|
||||||
|
|
28
config.mk
Normal file
28
config.mk
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
|
||||||
|
|
||||||
|
MAJOR := 5
|
||||||
|
MINOR := 0
|
||||||
|
PATCH := 0
|
||||||
|
COMMIT := gc$(shell git rev-parse --short HEAD 2>/dev/null)
|
||||||
|
|
||||||
|
ifeq ($(COMMIT),gc)
|
||||||
|
COMMIT = gcunknown
|
||||||
|
endif
|
||||||
|
|
||||||
|
VERSION := $(MAJOR).$(MINOR).$(PATCH)-dev+$(COMMIT)
|
||||||
|
|
||||||
|
CXXFLAGS:=$(CXXFLAGS) -std=c++20 -Wall -Wextra -Werror=switch -Werror=return-type -Werror=unused-result
|
||||||
|
CPPFLAGS:=$(CPPFLAGS) -DMusique_Version='"$(VERSION)"' \
|
||||||
|
-Ilib/expected/ -I. -Ilib/rtmidi/ -Ilib/link/include -Ilib/asio/include/ -Ilib/edit_distance.cc/ -Ilib/replxx/include -DREPLXX_STATIC
|
||||||
|
LDFLAGS=-flto
|
||||||
|
LDLIBS= -lpthread
|
||||||
|
|
||||||
|
RELEASE_FLAGS=-O2
|
||||||
|
DEBUG_FLAGS=-O0 -ggdb -fsanitize=undefined -DDebug
|
||||||
|
|
||||||
|
ifeq ($(shell uname),Darwin)
|
||||||
|
os=macos
|
||||||
|
else
|
||||||
|
os=linux
|
||||||
|
endif
|
||||||
|
|
20
doc/Makefile
20
doc/Makefile
@ -1,20 +0,0 @@
|
|||||||
# Minimal makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line, and also
|
|
||||||
# from the environment for the first two.
|
|
||||||
SPHINXOPTS ?=
|
|
||||||
SPHINXBUILD ?= sphinx-build
|
|
||||||
SOURCEDIR = source
|
|
||||||
BUILDDIR = build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
|
||||||
help:
|
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
|
|
||||||
.PHONY: help Makefile
|
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
||||||
%: Makefile
|
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
55
doc/index.md
Normal file
55
doc/index.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Musique interpreter documentation
|
||||||
|
|
||||||
|
This documentation system contains information for programmers that will like to contribute or learn about Musique interpreter (and [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)).
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build you need to have installed:
|
||||||
|
|
||||||
|
- Modern C++ compiler compatible with GNU compund expression extension and C++20 support;
|
||||||
|
- Following libraries when targetting GNU/Linux: `libreadline`, `libasound`.
|
||||||
|
|
||||||
|
Then all you have to do is run `make` in main source directory.
|
||||||
|
|
||||||
|
## Using interpreter as a library
|
||||||
|
|
||||||
|
Interpreter usage consist of three steps:
|
||||||
|
|
||||||
|
- creating chosen MIDI support for an Interpreter
|
||||||
|
- creating Interpreter instance
|
||||||
|
- parsing and evaluating source code
|
||||||
|
|
||||||
|
Parsing and evaluating may result in an error. For this case Result type offers `error()` method to get produced error and `has_value()` to check if computation was successfull.
|
||||||
|
|
||||||
|
### Simple example
|
||||||
|
|
||||||
|
We define `run` function that will do steps above, to execute provided string.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void run(std::string_view source)
|
||||||
|
{
|
||||||
|
Interpreter interpreter;
|
||||||
|
|
||||||
|
// We don't want midi support so we ignore it
|
||||||
|
interpreter.midi_connection = nullptr;
|
||||||
|
|
||||||
|
// We set filename used in error reporting to "example"
|
||||||
|
auto ast = Parser::parse(source, "example");
|
||||||
|
|
||||||
|
// Check if file was properly parsed. If not print error message and exit
|
||||||
|
if (!ast.has_value()) {
|
||||||
|
std::cerr << ast.error() << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate program
|
||||||
|
auto result = interpreter.eval(std::move(ast));
|
||||||
|
if (result.has_value()) {
|
||||||
|
std::cout << *result << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << result.error() << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When in doubt see `src/main.cc` as example on library usage.
|
285
doc/musique-vs-languages-cheatsheet.template
Normal file
285
doc/musique-vs-languages-cheatsheet.template
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
TITLE Porównanie Musique z typowymi językami programowania
|
||||||
|
|
||||||
|
BEGIN CSS
|
||||||
|
|
||||||
|
table, tr, td {
|
||||||
|
font-size: 12pt;
|
||||||
|
border: 1pt solid #DDDDDD;
|
||||||
|
border-collapse: collapse;
|
||||||
|
vertical-align: top;
|
||||||
|
tab-size: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
END CSS
|
||||||
|
|
||||||
|
BEGIN INTRO
|
||||||
|
<h1>Ściągawka Musique, a Python i Ruby</h1>
|
||||||
|
Ponieważ Musique jest kierowany do osób posiadających doświadczenie z muzyką algorytmiczną, szybkim sposobem na podstawowe poznanie języka jest porównanie z innymi technologiami w tej dziedzinie. Ten dokument służy bardziej ukazaniu różnic niż omówieniu samego języka.
|
||||||
|
END INTRO
|
||||||
|
|
||||||
|
BEGIN TABLE
|
||||||
|
|
||||||
|
SECTION Podstawy
|
||||||
|
|
||||||
|
n Kategoria
|
||||||
|
m Musique
|
||||||
|
p Python
|
||||||
|
r Ruby (SonicPi)
|
||||||
|
c Komentarz
|
||||||
|
|
||||||
|
n Deklaracja zmiennej
|
||||||
|
m x := 0
|
||||||
|
p x = 0
|
||||||
|
r x = 0
|
||||||
|
c Zmienne należy zadeklarować by móc z nich korzystać
|
||||||
|
|
||||||
|
n Aktualizacja wartości zmiennej
|
||||||
|
m x = 1
|
||||||
|
r x = 1
|
||||||
|
p x = 1
|
||||||
|
|
||||||
|
n Operacje matematyczne
|
||||||
|
m x = 10 * 30 - 40 ** 2
|
||||||
|
p x = 10 * 30 - 40 ** 2
|
||||||
|
r x = 10 * 30 - 40 ** 2
|
||||||
|
c Zarówno Python, Ruby jak i Musique posiadają operator potęgi **
|
||||||
|
|
||||||
|
n Funkcja anonimowa
|
||||||
|
m add := (x y | x + y)
|
||||||
|
p add = lambda x, y: x + y
|
||||||
|
r add = ->(x, y) { x + y }
|
||||||
|
|
||||||
|
n Deklaracja funkcji
|
||||||
|
m add := (x y |
|
||||||
|
m say x y,
|
||||||
|
m x + y
|
||||||
|
m )
|
||||||
|
p def add(x, y):
|
||||||
|
p print(x, y)
|
||||||
|
p return x + y
|
||||||
|
r def add(x, y)
|
||||||
|
r puts x, y
|
||||||
|
r return x + y
|
||||||
|
r end
|
||||||
|
c Musique nie rozróżnia funkcji anonimowych i zadeklarowanych
|
||||||
|
|
||||||
|
n Wywoływanie funkcji
|
||||||
|
m add 1 3
|
||||||
|
p add(1, 3)
|
||||||
|
r add 1, 3
|
||||||
|
|
||||||
|
n Wywołanie funkcji
|
||||||
|
n nie przymujących argumentów
|
||||||
|
m constant := (say 42, 10),
|
||||||
|
m say (call foo)
|
||||||
|
p def constant():
|
||||||
|
p print(42)
|
||||||
|
p return 10
|
||||||
|
p print(constant())
|
||||||
|
r def constant()
|
||||||
|
r puts(42)
|
||||||
|
r return 10
|
||||||
|
r end
|
||||||
|
r puts constant
|
||||||
|
|
||||||
|
n Instrukcja warunkowa
|
||||||
|
m if (n == 42)
|
||||||
|
m (say 1)
|
||||||
|
m (say 2)
|
||||||
|
p if n == 42:
|
||||||
|
p print(1)
|
||||||
|
p else:
|
||||||
|
p print(2)
|
||||||
|
r if n == 42
|
||||||
|
r puts 1
|
||||||
|
r else
|
||||||
|
r puts 2
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Wyrażenie warunkowe
|
||||||
|
m x := if (n == 42) 1 2
|
||||||
|
p x = 1 if n == 42 else 2
|
||||||
|
r x = n == 42 ? 1 : 2
|
||||||
|
|
||||||
|
SECTION Tablice
|
||||||
|
|
||||||
|
n Kategoria
|
||||||
|
m Musique
|
||||||
|
p Python
|
||||||
|
r Ruby (SonicPi)
|
||||||
|
c Komentarz
|
||||||
|
|
||||||
|
n Tablice
|
||||||
|
m x = (1, 2, 3, 4)
|
||||||
|
p x = [1, 2, 3, 4]
|
||||||
|
r x = [1, 2, 3, 4]
|
||||||
|
c W Musique funkcja anonimowa nie przyjmująca argumentów
|
||||||
|
c jak i tablica są tożsame.
|
||||||
|
|
||||||
|
n Nty element tablicy
|
||||||
|
m x[n]
|
||||||
|
p x[n]
|
||||||
|
r x[n]
|
||||||
|
|
||||||
|
n Aktualizacja ntego elementu tablicy
|
||||||
|
m x = update x n 10
|
||||||
|
p x[n] = 10
|
||||||
|
r x[n] = 10
|
||||||
|
|
||||||
|
n Tablica od 0 do 9 włącznie
|
||||||
|
m x = up 10
|
||||||
|
p x = list(range(10))
|
||||||
|
r x = [*0..9]
|
||||||
|
|
||||||
|
n Tablica od 1 do 10 włącznie
|
||||||
|
m x = 1 + up 10
|
||||||
|
m lub x = range 1 11
|
||||||
|
p x = list(range(1, 11))
|
||||||
|
r x = [*1..10]
|
||||||
|
|
||||||
|
n Tablica od 9 do 0 włącznie
|
||||||
|
m x = down 10
|
||||||
|
m lub x = reverse (up 10)
|
||||||
|
p x = list(range(9, -1, -1))
|
||||||
|
p lub x = list(reversed(range(10)))
|
||||||
|
r x = 9.downto(0).to_a
|
||||||
|
|
||||||
|
n Iloczyn elementów tablicy
|
||||||
|
m fold '* (1 + up 5)
|
||||||
|
p functools.reduce(
|
||||||
|
p operator.mul, range(1, 6), 1)
|
||||||
|
r [*1..5].inject(:*)
|
||||||
|
c Musique pozwala zmienić dowolny operator w funkcję
|
||||||
|
c poprzez zapis 'operator jak '* w przykładzie
|
||||||
|
|
||||||
|
n Iteracja po elementach tablicy
|
||||||
|
m for (up 5) (i | say i)
|
||||||
|
p for i in range(5):
|
||||||
|
p print(i)
|
||||||
|
r (0..4).each do |i|
|
||||||
|
r puts i
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Sortowanie tablicy
|
||||||
|
m xs := sort (1, 5, 3, 3, 2)
|
||||||
|
p xs = sorted([1, 5, 3, 3, 2])
|
||||||
|
r xs = [1, 5, 3, 3, 2].sort
|
||||||
|
|
||||||
|
n Sortowanie wielu tablic w jedną
|
||||||
|
m xs := sort (1, 5, 3, 3, 2)
|
||||||
|
m (3, 4, 5) 1 2 3
|
||||||
|
p xs = sorted(itertools.chain(
|
||||||
|
p [1, 5, 3, 3, 2], [3, 4, 5],
|
||||||
|
p [1], [2], [3]
|
||||||
|
p ))
|
||||||
|
r [[1, 5, 3, 3, 2], [3, 4, 5],
|
||||||
|
r [1], [2], [3]
|
||||||
|
r ].flatten.sort
|
||||||
|
c Wiele operacji na tablicach może być wykonywane na dowolnej kombinacji
|
||||||
|
c tablic i pojedyńczych wartości. Tworzy to jedną tablicę wykoniową.
|
||||||
|
|
||||||
|
SECTION Muzyka
|
||||||
|
|
||||||
|
n Kategoria
|
||||||
|
m Musique
|
||||||
|
r SonicPi
|
||||||
|
c Komentarz
|
||||||
|
|
||||||
|
n Zmiana tempa na 90
|
||||||
|
m bpm 90
|
||||||
|
r use_bpm 90
|
||||||
|
|
||||||
|
n Zmiana domyślnej długości nuty na półnutę
|
||||||
|
m len 1/2
|
||||||
|
c w SonicPi nie ma domyślnej długości nuty;
|
||||||
|
c za każdym razem trzeba ją definiować
|
||||||
|
|
||||||
|
n Zmiana oktawy do 4tej
|
||||||
|
m oct 4,
|
||||||
|
c w SonicPi domyślna oktawa
|
||||||
|
c jest ustalona jako 4
|
||||||
|
|
||||||
|
n C w 4 oktawie
|
||||||
|
m play c4
|
||||||
|
r play 60
|
||||||
|
|
||||||
|
n Akord C-dur
|
||||||
|
m play (c & e & g)
|
||||||
|
m lub play (chord c e g)
|
||||||
|
r play :C4
|
||||||
|
r play :E4
|
||||||
|
r play :G4
|
||||||
|
r lub play chord(:C4, :major)
|
||||||
|
|
||||||
|
n Akord C-dur w 8 oktawie
|
||||||
|
m play (c8 & e8 & g8)
|
||||||
|
r play :C8
|
||||||
|
r play :E8
|
||||||
|
r play :G8
|
||||||
|
r lub play chord(:C8, :major)
|
||||||
|
|
||||||
|
n C w 4 oktawie, półnuta
|
||||||
|
m play (c4 hn)
|
||||||
|
m lub play (c4 (1/2))
|
||||||
|
m lub play (c4 0.5)
|
||||||
|
r play 60, sustain: 2
|
||||||
|
c w SonicPi możliwa jest kontrola obwiedni ADSR za pomocą
|
||||||
|
c parametrów attack, delay, sustain i release
|
||||||
|
|
||||||
|
n Sekwencja C, E i G w oktawie 4, półnuty, <br />zagrane jedna po drugiej
|
||||||
|
m play (len (1/2), c4 e4 g4)
|
||||||
|
r [:C4, :E4, :G4].each do |i|
|
||||||
|
r play i, sustain: 2
|
||||||
|
r sleep 2
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Sekwencja C, D, E, F, G,<br/>z nutą A graną przez cały czas trwania sekwencji
|
||||||
|
m par a (c, d, e, f, g)
|
||||||
|
r in_thread do
|
||||||
|
r [:C4, :D4, :E4, :F4, :G4].each do |i|
|
||||||
|
r play i
|
||||||
|
r sleep 1
|
||||||
|
r end
|
||||||
|
r end
|
||||||
|
r in_thread do
|
||||||
|
r play :A4, sustain: 5
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Dwie melodie grane współbieżnie
|
||||||
|
m sim (c 4 c 3 c 2) (e 4 e 3 e 2)
|
||||||
|
r in_thread do
|
||||||
|
r [:C4, :C3, :C2].each do |i|
|
||||||
|
r play i
|
||||||
|
r sleep 1
|
||||||
|
r end
|
||||||
|
r end
|
||||||
|
r in_thread do
|
||||||
|
r [:E4, :E3, :E2].each do |i|
|
||||||
|
r play i
|
||||||
|
r sleep 1
|
||||||
|
r end
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Zagranie losowej nuty spośród C, E, G
|
||||||
|
m play (pick (c e g))
|
||||||
|
r play choose([:C, :E, :G])
|
||||||
|
|
||||||
|
n Zagranie sekwencji nut C, E, G w losowej kolejności
|
||||||
|
m play (shuffle (c e g))
|
||||||
|
r [:C, :E, :G].shuffle().each do |i|
|
||||||
|
r play i, sustain: 1
|
||||||
|
r sleep 1
|
||||||
|
r end
|
||||||
|
|
||||||
|
n Zagranie sekwencji C, E, G od tyłu
|
||||||
|
m play (reverse (c e g))
|
||||||
|
r [:C, :E, :G].reverse.each do |i|
|
||||||
|
r play i, sustain: 1
|
||||||
|
r sleep 1
|
||||||
|
r end
|
||||||
|
|
||||||
|
END TABLE
|
180
doc/operators.md
Normal file
180
doc/operators.md
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# Lista wbudowanych operatorów języka Musique
|
||||||
|
|
||||||
|
## Operatory arytmetyczne
|
||||||
|
|
||||||
|
- `+` – operator:
|
||||||
|
- dodawania (liczby całkowite i ułamki):
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 + 3
|
||||||
|
5
|
||||||
|
> (1/3) + (1/4)
|
||||||
|
7/12
|
||||||
|
> 1 + (up 10)
|
||||||
|
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
|
||||||
|
```
|
||||||
|
|
||||||
|
- inkrementacji zmiennej (liczby lub akordu, w tym w szczególności pojedynczeń nuty):
|
||||||
|
|
||||||
|
```
|
||||||
|
> c + 1
|
||||||
|
c#
|
||||||
|
c4 + 2
|
||||||
|
hord[d; f#]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `-` – operator odejmowania/dekrementacji – analogicznie do operatora `+`;
|
||||||
|
|
||||||
|
- `*` – operator:
|
||||||
|
|
||||||
|
- mnożenia (liczby całkowite i ułamki):
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 * 5
|
||||||
|
10
|
||||||
|
> (1/3) * (1/4)
|
||||||
|
1/12
|
||||||
|
> 2 * (up 10)
|
||||||
|
[0; 2; 4; 6; 8; 10; 12; 14; 16; 18]
|
||||||
|
```
|
||||||
|
|
||||||
|
- powtarzania – zwraca określoną liczbę powtórzeń danego dźwięku:
|
||||||
|
|
||||||
|
```
|
||||||
|
> a * 4
|
||||||
|
[a; a; a; a]
|
||||||
|
> a3 * 4
|
||||||
|
[chord[a; c]; chord[a; c]; chord[a; c]; chord[a; c]]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `/` – operator dzielenia – *wektor może być wyłącznie dzielną*:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 4 / 2
|
||||||
|
2
|
||||||
|
> 5 / 7
|
||||||
|
5/7
|
||||||
|
> (2/3) / (3/5)
|
||||||
|
10/9
|
||||||
|
> (up 10) / 2
|
||||||
|
[0; 1/2; 1; 3/2; 2; 5/2; 3; 7/2; 4; 9/2]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `%` – operator działania modulo (wynikiem jest reszta z dzielenia) – *nie działa dla ułamków*, *wektor może być wyłącznie dzielną*:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 3 % 3
|
||||||
|
0
|
||||||
|
> 6 % 5
|
||||||
|
1
|
||||||
|
> (up 10) % 2
|
||||||
|
[0; 1; 0; 1; 0; 1; 0; 1; 0; 1]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `**` – operator potęgowania – *wykładnikiem nie może być ułamek*:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 ** 8
|
||||||
|
256
|
||||||
|
> (2/3) ** 3
|
||||||
|
8/27
|
||||||
|
> (up 10) ** 2
|
||||||
|
[0; 1; 4; 9; 16; 25; 36; 49; 64; 81]
|
||||||
|
> 2 ** (up 10)
|
||||||
|
[1; 2; 4; 8; 16; 32; 64; 128; 256; 512]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Operatory porównawcze
|
||||||
|
|
||||||
|
- `!=` – operator "nie równa się":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 != 3
|
||||||
|
true
|
||||||
|
> a != a
|
||||||
|
false
|
||||||
|
> 3 != (up 5)
|
||||||
|
[true; true; true; false; true]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<` – operator "mniejsze niż":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 < 3
|
||||||
|
true
|
||||||
|
> a < a
|
||||||
|
false
|
||||||
|
> 3 < (up 5)
|
||||||
|
[true; true; true; false; false]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `<=` – operator "mniejsze lub równe":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 <= 3
|
||||||
|
true
|
||||||
|
> a <= a
|
||||||
|
true
|
||||||
|
> 3 <= 2
|
||||||
|
false
|
||||||
|
> 3 <= (up 5)
|
||||||
|
[true; true; true; true; false]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `==` – operator "równe":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 == 3
|
||||||
|
false
|
||||||
|
> a == a
|
||||||
|
true
|
||||||
|
> 3 == (up 5)
|
||||||
|
[false; false; false; true; false]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `>` – operator "większe niż":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 > 3
|
||||||
|
false
|
||||||
|
> a > a
|
||||||
|
true
|
||||||
|
> 3 > (up 5)
|
||||||
|
[false; false; false; false; true]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `>=` – operator "większe lub równe":
|
||||||
|
|
||||||
|
```
|
||||||
|
> 2 >= 3
|
||||||
|
false
|
||||||
|
> a >= a
|
||||||
|
true
|
||||||
|
> 3 >= 2
|
||||||
|
true
|
||||||
|
> 3 >= (up 5)
|
||||||
|
[false; false; false; true; true]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pozostałe operatory
|
||||||
|
|
||||||
|
- `.` – operator indeksu (zwraca wskazany element, liczone od 0):
|
||||||
|
|
||||||
|
```
|
||||||
|
> A:=[1; 3; 5]
|
||||||
|
> A . 1
|
||||||
|
3
|
||||||
|
> (up 7).4
|
||||||
|
3
|
||||||
|
```
|
||||||
|
|
||||||
|
- `&` – operator łączenia:
|
||||||
|
|
||||||
|
```
|
||||||
|
> c & a
|
||||||
|
chord[c; a]
|
||||||
|
> [1;3;5] & [2;4;6]
|
||||||
|
[1; 3; 5; 2; 4; 6]
|
||||||
|
> (up 7) & (down 9)
|
||||||
|
[0; 1; 2; 3; 4; 5; 6; 8; 7; 6; 5; 4; 3; 2; 1; 0]
|
||||||
|
```
|
@ -1,5 +0,0 @@
|
|||||||
Sphinx==4.5.0
|
|
||||||
breathe==4.33.1
|
|
||||||
exhale==0.3.1
|
|
||||||
recommonmark==0.7.1
|
|
||||||
sphinx-rtd-theme==1.0.0
|
|
@ -1,54 +0,0 @@
|
|||||||
program = { expression, ws*, ";", { ws*, ";" }, ws* } ;
|
|
||||||
block = "[", program, "]" ;
|
|
||||||
|
|
||||||
(* At interpreter runtime it is determined which symbols pass as operators, and which not *)
|
|
||||||
expression = value, ws*, operator, ws*, expression
|
|
||||||
| operator, ws*, value
|
|
||||||
| value ;
|
|
||||||
|
|
||||||
value = note
|
|
||||||
| chord
|
|
||||||
| symbol
|
|
||||||
| block
|
|
||||||
| number
|
|
||||||
| ( "(", expression, ")" ) ;
|
|
||||||
|
|
||||||
symbol = ( valid-symbol-start-characters, { valid-symbol-characters } ) - note - chord;
|
|
||||||
valid-symbol-start-characters = uniletter | "_" | "@" | "$" | "#" ;
|
|
||||||
valid-symbol-characters = valid-symbol-start-characters | unidigit | "-" ;
|
|
||||||
|
|
||||||
operator = operator-symbols, { operator-symbols } ;
|
|
||||||
operator-symbols = "+" | "-" | "*" | "/" | "%" | "!"
|
|
||||||
| "<" | ">" | "v" | "^" | "=" | ":" ;
|
|
||||||
|
|
||||||
(********************************* Literały liczbowe *********************************)
|
|
||||||
number = floating-point | fraction ;
|
|
||||||
|
|
||||||
(* Dopuszcza następujące zapisy: 1/2, *)
|
|
||||||
fraction = digits+, ws*, "/", ws*, digits+ ;
|
|
||||||
|
|
||||||
(* Dopuszcza następujące zapisy: -123.456, 123.456, .456; Notacja naukowa nie jest wspierana *)
|
|
||||||
floating-point = ( ["-"], digits+, [ ".", digits+ ] ) | ( ".", digits+ );
|
|
||||||
|
|
||||||
|
|
||||||
(********************************* Literały muzyczne *********************************)
|
|
||||||
(* DSL do definiowania muzycznych wartości. Brakuje notacji dla akordów, przewrotów itd *)
|
|
||||||
note = note-letter, ["#"], [ws*, octave] ;
|
|
||||||
note-letter = "c" | "C" | "d" | "D" | "e" | "E" | "f" | "F" | "g" | "G" | "a" | "A" | "h" | "H" | "b" | "B" ;
|
|
||||||
octave = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" ;
|
|
||||||
|
|
||||||
chord = note-letter, ["#"], [ ("1" | "2" | "5" | "7" ), [ "," | "'" ] ];
|
|
||||||
|
|
||||||
(********************************* Definicje pomocnicze *********************************)
|
|
||||||
|
|
||||||
(* Unicode helpers, based on Go's compiler source code *)
|
|
||||||
uniletter = ? all characters that are considered letters in unicode ?;
|
|
||||||
unidigit = ? all characters that are considered digits in unicode ?;
|
|
||||||
|
|
||||||
digits+ = digit, { digits } ;
|
|
||||||
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
|
|
||||||
|
|
||||||
(* Whitespace helpers *)
|
|
||||||
ws* = { ws } ;
|
|
||||||
ws+ = ws, { ws } ;
|
|
||||||
ws = ? all characters that are considered ascii whitespace ? ;
|
|
@ -1,55 +0,0 @@
|
|||||||
# This file only contains a selection of the most common options. For a full
|
|
||||||
# list see the documentation:
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
|
|
||||||
project = 'Musique'
|
|
||||||
copyright = '2022, Robert Bendun'
|
|
||||||
author = 'Robert Bendun'
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
|
||||||
|
|
||||||
extensions = [
|
|
||||||
"sphinx_rtd_theme",
|
|
||||||
"breathe",
|
|
||||||
"recommonmark",
|
|
||||||
"exhale"
|
|
||||||
]
|
|
||||||
|
|
||||||
breathe_projects = {
|
|
||||||
"musique": "../build/doxygen/xml"
|
|
||||||
}
|
|
||||||
|
|
||||||
breathe_default_project = "musique"
|
|
||||||
|
|
||||||
exhale_args = {
|
|
||||||
"containmentFolder": "./api",
|
|
||||||
"rootFileName": "musique-root.rst",
|
|
||||||
"createTreeView": True,
|
|
||||||
"doxygenStripFromPath": ".."
|
|
||||||
}
|
|
||||||
|
|
||||||
primary_domain = "cpp"
|
|
||||||
highlight_language = "cpp"
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This pattern also affects html_static_path and html_extra_path.
|
|
||||||
exclude_patterns = []
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
@ -1,22 +0,0 @@
|
|||||||
.. Musique documentation master file, created by
|
|
||||||
sphinx-quickstart on Sun May 8 17:37:28 2022.
|
|
||||||
You can adapt this file completely to your liking, but it should at least
|
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
Welcome to Musique's documentation!
|
|
||||||
===================================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Contents:
|
|
||||||
|
|
||||||
api/musique-root
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
|
||||||
==================
|
|
||||||
|
|
||||||
* :ref:`genindex`
|
|
||||||
* :ref:`modindex`
|
|
||||||
* :ref:`search`
|
|
298
doc/wprowadzenie.md
Normal file
298
doc/wprowadzenie.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
---
|
||||||
|
title: Wprowadzenie do języka Musique
|
||||||
|
date: 2022-11-12
|
||||||
|
author: Robert Bendun <robben@st.amu.edu.pl>
|
||||||
|
---
|
||||||
|
|
||||||
|
# Wprowadzenie do języka Musique
|
||||||
|
|
||||||
|
W dalszej części tekstu przyjmujemy następujące konwencje:
|
||||||
|
|
||||||
|
`>` – jest to [znak zachęty](https://pl.wikipedia.org/wiki/Znak_zach%C4%99ty) i wskazuje gotowość programu Musique do wprowadzania tekstu. Jeżeli widzisz taki znak, oznacza to, że jesteś w programie Musique.
|
||||||
|
|
||||||
|
Przykładowo:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 3 + 4
|
||||||
|
7
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
W tym przykładzie wykonujemy `3 + 4` , zatwierdzając ENTEREM, w zwrocie otrzymując – w tym konkretnym przypadku – wynik operacji.
|
||||||
|
|
||||||
|
Przykłady w tym wprowadzeniu mogą rozpoczynać się od `>` – oznacza to, że polecenia wprowadzono w sesji interaktywnej, lub bez tego znaku – wtedy traktujemy przykład jako zapisany plik z poleceniami.
|
||||||
|
Nie ma różnic pomiędzy wykonywaniem poleceń języka Musique zawartych w pliku, a poleceniami wprowadzanymi w sesji interaktywnej – wybór pozostawiamy użytkownikowi.
|
||||||
|
|
||||||
|
Można wykonać złożone polecenia (które w pliku zostałyby rozbite na kilka linii) w sesji interaktywnej - należy wtedy wpisać je w formie jednej linii.
|
||||||
|
|
||||||
|
## Nuty, pauzy, akordy
|
||||||
|
|
||||||
|
W tej sekcji zostanie omówione tworzenie prostych utworów z wykorzystaniem nut, akordów oraz prostych sekwencji.
|
||||||
|
|
||||||
|
### Nuty
|
||||||
|
|
||||||
|
Aby zagrać nutę C wpisz `play c` w uruchomionym programie Musique.
|
||||||
|
|
||||||
|
```
|
||||||
|
> play c
|
||||||
|
```
|
||||||
|
|
||||||
|
Możesz zagrać inną nutę jak E:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play e
|
||||||
|
```
|
||||||
|
|
||||||
|
lub wiele nut po kolei – należy umieścić je w nawiasach okrągłych, rozdzielone przecinkami:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c, e, g)
|
||||||
|
```
|
||||||
|
|
||||||
|
Dostępne dźwięki bazowe to kolejno: `c`, `d`, `e`, `f`, `g`, `a`, `b`. Można je modyfikować poprzez znaki:
|
||||||
|
|
||||||
|
- `#` lub `s` podwyższający wysokość dźwięku o pół tonu (krzyżyk, **s**harp)
|
||||||
|
- `b` lub `f` obniżający wysokość dźwięku o pół tonu (**b**emol, **f**lat)
|
||||||
|
|
||||||
|
pozwala to przykładowo tworzyć:
|
||||||
|
|
||||||
|
- `c#` - dźwięk Cis
|
||||||
|
- `c##` - dźwięk D
|
||||||
|
- `eb` - dźwięk Dis
|
||||||
|
|
||||||
|
Aby dźwięk został odtworzony w wybranej oktawie można dołączyć do znaku dźwięku liczbową wartość oktawy - `c4` to dźwięk C w 4 oktawie, `c#8` to dźwięk Cis w 8 oktawie, itp.
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c4, c5, c6)
|
||||||
|
```
|
||||||
|
|
||||||
|
Aby dźwięk trwał określoną długość należy podać jako dodatkowy parametr pożądaną wartość, przykładowo:
|
||||||
|
|
||||||
|
Sekwencja złożona z dźwięku C w 4. oktawie trwającym ćwierćnutę, dźwięku D w 5. oktawie trwającym półnutę oraz dźwięku E w 4. oktawie trwającym całą nutę wygląda następująco:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c4 (1/4), d5 (1/2), e4 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
Można uprościć zapis korzystając z predefiniowanych czasów dźwięków:
|
||||||
|
|
||||||
|
| nazwa | czas trwania | liczbowo |
|
||||||
|
| :-: | :-: | :-: |
|
||||||
|
| `wn` | cała nuta | `1` |
|
||||||
|
| `dwn` | cała nuta z kropką | `3/2` |
|
||||||
|
| `hn` | półnuta | `1/2` |
|
||||||
|
| `dhn` | półnuta z kropką | `3/4` |
|
||||||
|
| `qn` | ćwierćnuta | `1/4` |
|
||||||
|
| `dqn` | ćwierćnuta z kropką | `3/8` |
|
||||||
|
| `en` | ósemka | `1/8` |
|
||||||
|
| `den` | ósemka z kropką | `3/16` |
|
||||||
|
| `sn` | szesnastka | `1/16` |
|
||||||
|
| `dsn` | szesnastka z kropką | `3/32` |
|
||||||
|
| `tn` | trzydziestkadwójka | `1/32` |
|
||||||
|
|
||||||
|
Korzystając z tych długości możemy powyższy przykład zapisać równoważnie w ten sposób:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c4 qn, d5 hn, e4 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pauzy
|
||||||
|
|
||||||
|
Pauzy stosuje się poprzez użycie litery `p`:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c4 hn, p qn, c4 hn, p qn, c4 hn)
|
||||||
|
```
|
||||||
|
|
||||||
|
Pauzy zachowują się identycznie jak nuty opisane powyżej.
|
||||||
|
|
||||||
|
### Akordy
|
||||||
|
|
||||||
|
Aby odegrać akord należy umieścić symbole dźwięków, z których miałby się składać, w wywołaniu funkcji `chord`:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (chord (c, e, g))
|
||||||
|
```
|
||||||
|
|
||||||
|
W utworze możemy chcieć częściej używać tych samych akordów czy sekwencji. Przypisanie ich do wybranej nazwy wyglądałoby tak:
|
||||||
|
|
||||||
|
```
|
||||||
|
> sekwencja := (c, e, g)
|
||||||
|
> sekwencja
|
||||||
|
(c, e, g)
|
||||||
|
```
|
||||||
|
|
||||||
|
Wpisanie samej nazwy pozwala zobaczyć co się pod nią znajduje.
|
||||||
|
|
||||||
|
Zapisaną sekwencję możemy przerobić na akord, ponownie wykorzystując funkcję `chord`:
|
||||||
|
|
||||||
|
```
|
||||||
|
> C := chord sekwencja
|
||||||
|
> C
|
||||||
|
chord (c, e, g)
|
||||||
|
```
|
||||||
|
|
||||||
|
i następnie go odtworzyć:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play C
|
||||||
|
```
|
||||||
|
|
||||||
|
Należy zwrócić uwagę, że Musique rozróżnia wielkość liter. Ponadto nazw będących oznaczeniami dźwięków jak `c` bądź `cffff` nie można używać jako nazw dla zmiennych.
|
||||||
|
|
||||||
|
## Metody tworzenia sekwencji
|
||||||
|
|
||||||
|
### Wielokrotne powtarzanie tego samego dźwięku
|
||||||
|
|
||||||
|
Wielokrotne powtarzanie tego samego dźwięku można osiągnąć poprzez mnożenie dźwięku przez ilość powtórzeń:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 3 * c
|
||||||
|
(c, c, c)
|
||||||
|
> c * 3
|
||||||
|
(c, c, c)
|
||||||
|
> 3 * (c, e)
|
||||||
|
(c, e, c, e, c, e)
|
||||||
|
```
|
||||||
|
|
||||||
|
Operacja ta zachowuje długości i oktawy:
|
||||||
|
|
||||||
|
```
|
||||||
|
> 3 * (e4 qn, f8 tn)
|
||||||
|
(e4 1/4, f8 1/32, e4 1/4, f8 1/32, e4 1/4, f8 1/32)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Wybieranie losowego dźwięku z grupy
|
||||||
|
|
||||||
|
Funkcja `pick` pozwala na wybór losowego elementu z sekwencji. Można użyć jej np. do grania dźwięku o losowej długości:
|
||||||
|
|
||||||
|
```
|
||||||
|
> play (c4 (pick qn hn))
|
||||||
|
```
|
||||||
|
|
||||||
|
W powyższym przykładzie dźwięk C w oktawie 4. zostanie zagrany losowo z długością ćwierćnuty lub półnuty.
|
||||||
|
|
||||||
|
### Losowe ustawienie elementów sekwencji
|
||||||
|
|
||||||
|
Funkcja `shuffle` pozwala na tworzenie sekwencji z losową kolejnością elementów, np:
|
||||||
|
|
||||||
|
```
|
||||||
|
> shuffle (c, e, f, g)
|
||||||
|
(f, g, e, c)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generowanie sekwencji w oparciu o liczbę półtonów
|
||||||
|
|
||||||
|
`dźwięk + liczba` przesuwa dany dźwięk o daną liczbę półtonów. Pozwala to tworzyć następujące sekwencje:
|
||||||
|
|
||||||
|
```
|
||||||
|
> c4 + (0, 1, 2, 3)
|
||||||
|
(c4, c#4, d4, d#4)
|
||||||
|
```
|
||||||
|
|
||||||
|
Podobny efekt można uzyskać funkcję `up` jako generator wartości liczbowych:
|
||||||
|
|
||||||
|
```
|
||||||
|
> up 5
|
||||||
|
(0, 1, 2, 3, 4)
|
||||||
|
> c4 + up 4
|
||||||
|
(c4, c#4, d4, d#4, e4)
|
||||||
|
> play (c4 + up 4)
|
||||||
|
```
|
||||||
|
|
||||||
|
Analogicznie działa funkcja `down`, generująca wartości liczbowe w kierunku zera:
|
||||||
|
|
||||||
|
```
|
||||||
|
> down 5
|
||||||
|
(4, 3, 2, 1, 0)
|
||||||
|
> c4 + down 5
|
||||||
|
(e4, d#4, d4, c#4, c4)
|
||||||
|
> play (c4 + down 5)
|
||||||
|
```
|
||||||
|
|
||||||
|
Możemy złączyć sekwencje przy pomocy operatora `&`:
|
||||||
|
|
||||||
|
```
|
||||||
|
> up 5 & down 5
|
||||||
|
(0, 1, 2, 3, 4, 4, 3, 2, 1, 0)
|
||||||
|
> play (c4 + up 5 & down 5)
|
||||||
|
```
|
||||||
|
|
||||||
|
Jeśli przeszkadza nam podwójnie zagrana nuta `e4` możemy ją wyeliminować funkcją `uniq`, która usuwa sąsiadujące ze sobą powtórzenia:
|
||||||
|
|
||||||
|
```
|
||||||
|
> uniq (up 5 & down 5)
|
||||||
|
(0, 1, 2, 3, 4, 3, 2, 1, 0)
|
||||||
|
> play (c4 + uniq (up 5 & down 5))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metody odtwarzania sekwencji
|
||||||
|
|
||||||
|
Musique posiada trzy główne metody odtwarzania sekwencji:
|
||||||
|
|
||||||
|
- `play` które odtwarza dźwięki w kolejności
|
||||||
|
- `par` które odtwarza pierwszy dźwięk równocześnie z pozostałymi
|
||||||
|
- `sim` który odtwarza każdą podaną mu sekwencję równocześnie
|
||||||
|
|
||||||
|
Każda z nich w momencie napotkania dźwięku z nieokreśloną oktawą lub długością wypełni ją według wartości *domyślnej* (wartości domyślne to: 4. oktawa, 120 bpm, ćwierćnuta).
|
||||||
|
|
||||||
|
Wartości domyślne można ustawiać przy pomocy funkcji `oct`, `len` oraz `bpm`. Poniższy przykład ustawia domyślną oktawę na 5, domyślną długość na półnutę oraz domyślne tempo na 100 uderzeń na minutę:
|
||||||
|
|
||||||
|
```
|
||||||
|
> oct 5
|
||||||
|
> len hn
|
||||||
|
> bpm 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### `play`
|
||||||
|
|
||||||
|
`play` przechodzi kolejno przez elementy sekwencji i kończy się po odtworzeniu wszystkich dźwięków.
|
||||||
|
|
||||||
|
Jeśli chcemy wykonać kilka `play` po sobie, możemy to osiągnąć rozdzielając je przecinkami – analogicznie do wspomnianych wcześniej sekwencji:
|
||||||
|
|
||||||
|
```
|
||||||
|
play (c qn, e qn, g hn),
|
||||||
|
play (16 * (f sn)),
|
||||||
|
play (c qn, e qn, g hn),
|
||||||
|
```
|
||||||
|
|
||||||
|
Uwaga – powyższy przykład reprezentuje polecenia zapisane w pliku (stosujemy konwencję rozszerzenia `.mq`) – wskazuje na to brak znaku zachęty `>`.
|
||||||
|
|
||||||
|
Można ten zapis uprościć:
|
||||||
|
|
||||||
|
```
|
||||||
|
play (
|
||||||
|
(c qn, e qn, g hn),
|
||||||
|
(16 * (f sn)),
|
||||||
|
(c qn, e qn, g hn),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
gdzie wcięcia i nowe linie zostały dodane dla poprawy czytelności.
|
||||||
|
|
||||||
|
### `par`
|
||||||
|
|
||||||
|
`par` umożliwa wykonanie pierwszego argumentu przez całą długość trwania pozostałych - niezależnie od tego jaka długość dźwięku została określona dla pierwszego z nich, zostanie dopasowany do sumy długości pozostałych dźwięków.
|
||||||
|
|
||||||
|
Przykład inspirowany Odą do Radości, w którym akord trwa przez całą długość odtwarzania sekwencyjnie pozostałych dźwięków. Wcześniej ustawiamy domyślną oktawę jako 5, by nie musieć powtarzać jej przy każdym dźwięku:
|
||||||
|
|
||||||
|
```
|
||||||
|
oct 5,
|
||||||
|
par (chord c3 g3 c4) (e, e, f, g)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `sim`
|
||||||
|
|
||||||
|
`sim` umożliwia wykonywanie równocześnie kilku sekwencji.
|
||||||
|
|
||||||
|
Poniżej "niepoprawna" metoda stworzenia akordu poprzez równocześne odtworzenie dźwięków c, e, g:
|
||||||
|
|
||||||
|
```
|
||||||
|
> sim c e g
|
||||||
|
```
|
||||||
|
|
||||||
|
Trzy dźwięki C w domyślnej oktawie o długości ćwierćnuty odtwarzane równocześnie wraz z pauzą ćwierćnutową i czterema dźwiękami D w 5. oktawie o długości szesnastki:
|
||||||
|
|
||||||
|
```
|
||||||
|
> sim (3 * c qn) (p qn, 4 * (d5 sn))
|
||||||
|
```
|
42
editor/musique.vim
Normal file
42
editor/musique.vim
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
" Vim syntax file
|
||||||
|
" Language: Musique
|
||||||
|
" Maintainer: Robert Bendun
|
||||||
|
" Latest Change: 2022-05-22
|
||||||
|
" Filenames: *.mq
|
||||||
|
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
syn keyword musiqueVariableDeclaration :=
|
||||||
|
syn keyword musiqueOperators * + - / < <= == >= > != . ** and or
|
||||||
|
|
||||||
|
syn match musiqueParameterSplitter display "|"
|
||||||
|
syn match musiqueExpressionDelimiter display ";"
|
||||||
|
|
||||||
|
syn match musiqueInteger display "[0-9][0-9_]*"
|
||||||
|
|
||||||
|
syn keyword musiqueConstant true false nil
|
||||||
|
|
||||||
|
syn keyword musiqueDefaultBuiltins bpm call ceil chord down flat floor fold for hash if incoming instrument len max min mix note_off note_on nprimes oct par partition permute pgmchange play program_change range reverse rotate round shuffle sim sort try typeof uniq unique up update
|
||||||
|
syn keyword musiqueLinuxBuiltins say
|
||||||
|
|
||||||
|
syn match musiqueComment "--.*$"
|
||||||
|
syn match musiqueComment "#!.*$"
|
||||||
|
|
||||||
|
syn region musiqueComment start="----*" end="----*"
|
||||||
|
|
||||||
|
syn region musiqueBlock matchgroup=musiqueParen start="\[" skip="|.\{-}|" matchgroup=musiqueParen end="\]" fold transparent
|
||||||
|
|
||||||
|
let b:current_syntax = "musique"
|
||||||
|
|
||||||
|
hi def link musiqueVariableDeclaration Define
|
||||||
|
hi def link musiqueParameterSplitter Delimiter
|
||||||
|
hi def link musiqueExpressionDelimiter Delimiter
|
||||||
|
hi def link musiqueParen Delimiter
|
||||||
|
hi def link musiqueOperators Operator
|
||||||
|
hi def link musiqueComment Comment
|
||||||
|
hi def link musiqueInteger Number
|
||||||
|
hi def link musiqueConstant Constant
|
||||||
|
hi def link musiqueDefaultBuiltins Function
|
||||||
|
hi def link musiqueLinuxBuiltins Function
|
17
editor/vscode-musique/.vscode/launch.json
vendored
Normal file
17
editor/vscode-musique/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// A launch configuration that launches the extension inside a new window
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Extension",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
4
editor/vscode-musique/.vscodeignore
Normal file
4
editor/vscode-musique/.vscodeignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.vscode/**
|
||||||
|
.vscode-test/**
|
||||||
|
.gitignore
|
||||||
|
vsc-extension-quickstart.md
|
9
editor/vscode-musique/CHANGELOG.md
Normal file
9
editor/vscode-musique/CHANGELOG.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to the "musique" extension will be documented in this file.
|
||||||
|
|
||||||
|
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Initial release
|
65
editor/vscode-musique/README.md
Normal file
65
editor/vscode-musique/README.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# musique README
|
||||||
|
|
||||||
|
This is the README for your extension "musique". After writing up a brief description, we recommend including the following sections.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
|
||||||
|
|
||||||
|
For example if there is an image subfolder under your extension project workspace:
|
||||||
|
|
||||||
|
\!\[feature X\]\(images/feature-x.png\)
|
||||||
|
|
||||||
|
> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
If you have any requirements or dependencies, add a section describing those and how to install and configure them.
|
||||||
|
|
||||||
|
## Extension Settings
|
||||||
|
|
||||||
|
Include if your extension adds any VS Code settings through the `contributes.configuration` extension point.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
This extension contributes the following settings:
|
||||||
|
|
||||||
|
* `myExtension.enable`: Enable/disable this extension.
|
||||||
|
* `myExtension.thing`: Set to `blah` to do something.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
Calling out known issues can help limit users opening duplicate issues against your extension.
|
||||||
|
|
||||||
|
## Release Notes
|
||||||
|
|
||||||
|
Users appreciate release notes as you update your extension.
|
||||||
|
|
||||||
|
### 1.0.0
|
||||||
|
|
||||||
|
Initial release of ...
|
||||||
|
|
||||||
|
### 1.0.1
|
||||||
|
|
||||||
|
Fixed issue #.
|
||||||
|
|
||||||
|
### 1.1.0
|
||||||
|
|
||||||
|
Added features X, Y, and Z.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Working with Markdown
|
||||||
|
|
||||||
|
You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts:
|
||||||
|
|
||||||
|
* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux).
|
||||||
|
* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux).
|
||||||
|
* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets.
|
||||||
|
|
||||||
|
## For more information
|
||||||
|
|
||||||
|
* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown)
|
||||||
|
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
|
||||||
|
|
||||||
|
**Enjoy!**
|
26
editor/vscode-musique/language-configuration.json
Normal file
26
editor/vscode-musique/language-configuration.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
// symbol used for single line comment. Remove this entry if your language does not support line comments
|
||||||
|
"lineComment": "--",
|
||||||
|
// symbols used for start and end a block comment. Remove this entry if your language does not support block comments
|
||||||
|
"blockComment": [ "/*", "*/" ]
|
||||||
|
},
|
||||||
|
// symbols used as brackets
|
||||||
|
"brackets": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
],
|
||||||
|
// symbols that are auto closed when typing
|
||||||
|
"autoClosingPairs": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
],
|
||||||
|
// symbols that can be used to surround a selection
|
||||||
|
"surroundingPairs": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
]
|
||||||
|
}
|
25
editor/vscode-musique/package.json
Normal file
25
editor/vscode-musique/package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "musique",
|
||||||
|
"displayName": "Musique",
|
||||||
|
"description": "Support for Musique, programming language for musical expression",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.72.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"languages": [{
|
||||||
|
"id": "musique",
|
||||||
|
"aliases": ["Musique", "musique"],
|
||||||
|
"extensions": [".mq"],
|
||||||
|
"configuration": "./language-configuration.json"
|
||||||
|
}],
|
||||||
|
"grammars": [{
|
||||||
|
"language": "musique",
|
||||||
|
"scopeName": "source.musique",
|
||||||
|
"path": "./syntaxes/musique.tmLanguage.json"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
64
editor/vscode-musique/syntaxes/musique.tmLanguage.json
Normal file
64
editor/vscode-musique/syntaxes/musique.tmLanguage.json
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||||
|
"name": "Musique",
|
||||||
|
"foldingStartMarker": "\\[",
|
||||||
|
"foldingStopMarker": "^\\s*\\]|^\\s\\]",
|
||||||
|
"fileTypes": [
|
||||||
|
".mq"
|
||||||
|
],
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#numeric"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": ":=",
|
||||||
|
"name": "keyword.operator.declaration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "--[^-].*$",
|
||||||
|
"name": "comment.line.double-dash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "--+",
|
||||||
|
"end": "--+",
|
||||||
|
"name": "comment.block"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b(nil)\\b",
|
||||||
|
"name": "constant.language.nil"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b(a|b|c|d|e|f|g|h)[#sfb]?\\d*\\b",
|
||||||
|
"name": "constant.language.music"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b(true|false)\\b",
|
||||||
|
"name": "constant.language.boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b(bpm|call|ceil|chord|down|flat|floor|fold|for|hash|if|instrument|len|max|min|mix|note_off|note_on|nprimes|oct|par|partition|permute|pgmchange|play|program_change|range|reverse|rotate|round|scan|shuffle|sim|sort|try|typeof|uniq|unique|up|update|say)\\b",
|
||||||
|
"name": "entity.name.function.builtins"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(\\*|\\+|\\-|\/|\\\\)",
|
||||||
|
"name": "keyword.operator.arithmetic"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "---+()",
|
||||||
|
"begin": "/---+/",
|
||||||
|
"end": "/---+/",
|
||||||
|
"name": "comment.block.musique"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"numeric": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "(?<!\\w)-?[0-9]+",
|
||||||
|
"name": "constant.numeric.integer.musique"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scopeName": "source.musique"
|
||||||
|
}
|
29
editor/vscode-musique/vsc-extension-quickstart.md
Normal file
29
editor/vscode-musique/vsc-extension-quickstart.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Welcome to your VS Code Extension
|
||||||
|
|
||||||
|
## What's in the folder
|
||||||
|
|
||||||
|
* This folder contains all of the files necessary for your extension.
|
||||||
|
* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension.
|
||||||
|
* `syntaxes/musique.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization.
|
||||||
|
* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets.
|
||||||
|
|
||||||
|
## Get up and running straight away
|
||||||
|
|
||||||
|
* Make sure the language configuration settings in `language-configuration.json` are accurate.
|
||||||
|
* Press `F5` to open a new window with your extension loaded.
|
||||||
|
* Create a new file with a file name suffix matching your language.
|
||||||
|
* Verify that syntax highlighting works and that the language configuration settings are working.
|
||||||
|
|
||||||
|
## Make changes
|
||||||
|
|
||||||
|
* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
|
||||||
|
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
|
||||||
|
|
||||||
|
## Add more language features
|
||||||
|
|
||||||
|
* To add features such as IntelliSense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs
|
||||||
|
|
||||||
|
## Install your extension
|
||||||
|
|
||||||
|
* To start using your extension with Visual Studio Code copy it into the `<user home>/.vscode/extensions` folder and restart Code.
|
||||||
|
* To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension.
|
@ -1,3 +0,0 @@
|
|||||||
say (1 + 3);
|
|
||||||
say (3 * 10);
|
|
||||||
say 42
|
|
27
examples/assigments-state-management.mq
Normal file
27
examples/assigments-state-management.mq
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
----------------------------------
|
||||||
|
Simple variable assigment
|
||||||
|
----------------------------------
|
||||||
|
x := 10,
|
||||||
|
y := 20,
|
||||||
|
say x,
|
||||||
|
say y,
|
||||||
|
|
||||||
|
x = 30,
|
||||||
|
say x,
|
||||||
|
say y,
|
||||||
|
|
||||||
|
x = y,
|
||||||
|
say x,
|
||||||
|
say y,
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Array updates
|
||||||
|
----------------------------------
|
||||||
|
array := flat 1 2 3,
|
||||||
|
say array,
|
||||||
|
|
||||||
|
array = update array 1 10,
|
||||||
|
say array,
|
||||||
|
|
||||||
|
array = update array 1 (array.2),
|
||||||
|
say array,
|
5
examples/common-array-operations.mq
Normal file
5
examples/common-array-operations.mq
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
map := (fn array | result := (), for array (v | result = result & (| fn v) ), result),
|
||||||
|
drop := (n arr | arr[range n (len arr)]),
|
||||||
|
take := (n arr | arr[up n]),
|
||||||
|
filter := (predicate arr | arr[map predicate arr]),
|
||||||
|
|
13
examples/control-flow.mq
Normal file
13
examples/control-flow.mq
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
say (if true 4 2),
|
||||||
|
say (if false 4 2),
|
||||||
|
|
||||||
|
if true (say 4) (say 2),
|
||||||
|
if false (say 4) (say 2),
|
||||||
|
|
||||||
|
n := 0,
|
||||||
|
while (n < 5) (
|
||||||
|
say 'while n,
|
||||||
|
n = n + 1,
|
||||||
|
),
|
||||||
|
|
@ -1,12 +1,30 @@
|
|||||||
var for = [ start stop iteration |
|
----------------------------------------------------------------------------
|
||||||
if (start > stop)
|
This example shows how to implement factorial operation using different
|
||||||
[| nil ]
|
implementation techniques, showing how one can iterate and accumulate
|
||||||
[| iteration start; for (start + 1) stop iteration ]
|
using Musique programming language
|
||||||
];
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
var factorial = [n | if (n <= 1)
|
-- Calculate factorial using recursive approach
|
||||||
[| 1]
|
factorial_recursive := (n |
|
||||||
[| n * (factorial (n-1)) ]
|
if (n <= 1)
|
||||||
];
|
1
|
||||||
|
(n * (factorial_recursive (n-1)))
|
||||||
|
),
|
||||||
|
|
||||||
for 1 10 [i | say (factorial i)];
|
-- Calculate factorial using iterative approach
|
||||||
|
factorial_iterative := (n |
|
||||||
|
x := 1,
|
||||||
|
for (range 1 (n+1)) (i | x *= i),
|
||||||
|
x
|
||||||
|
),
|
||||||
|
|
||||||
|
-- Calculate factorial using composition of functions
|
||||||
|
factorial := (n | fold '* 1 (1 + up n)),
|
||||||
|
|
||||||
|
-- Gather all functions into array, and iterate over it
|
||||||
|
-- This allows to reduce repeatition of this test case
|
||||||
|
for (factorial_recursive, factorial_iterative, factorial) ( factorial |
|
||||||
|
for (up 10) ( n |
|
||||||
|
say (factorial (n)),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
5
examples/fib.mq
Normal file
5
examples/fib.mq
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fib := (n |
|
||||||
|
if (n <= 1)
|
||||||
|
n
|
||||||
|
(fib (n-1) + fib (n-2))
|
||||||
|
),
|
65
examples/for-elise.mq
Normal file
65
examples/for-elise.mq
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
----------------------------------------------
|
||||||
|
"Für Elise in A Minor" by Ludwig van Beethoven
|
||||||
|
WIP implemntation
|
||||||
|
----------------------------------------------
|
||||||
|
oct 5, bpm 72, len (1/16),
|
||||||
|
|
||||||
|
subsection1 := (
|
||||||
|
sim (a4 en) (a2 e3 a3),
|
||||||
|
play (oct 4, c e a),
|
||||||
|
|
||||||
|
sim (b4 en) (e2 e3 g#3),
|
||||||
|
play (oct 4, e g# b),
|
||||||
|
|
||||||
|
sim (c5 en) (a2 e3 a3),
|
||||||
|
play (e4 e5 d#5),
|
||||||
|
|
||||||
|
play e d# e b4 d c,
|
||||||
|
|
||||||
|
sim (a4 en) (a2 e3 a3),
|
||||||
|
play c4 e4 a4,
|
||||||
|
|
||||||
|
sim (b4 en) (e2 e3 g#3),
|
||||||
|
play d4 c5 b4,
|
||||||
|
),
|
||||||
|
|
||||||
|
section1 := ( n |
|
||||||
|
play e d#,
|
||||||
|
play e d# e b4 d c,
|
||||||
|
|
||||||
|
call subsection1,
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
( sim (a4 qn) (a2 e3 a3) )
|
||||||
|
( sim (a4 en) (a2 e3 a3)
|
||||||
|
, play b4 c5 d5
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
section2 := ( n |
|
||||||
|
sim (e5 den) (c3 g3 c4),
|
||||||
|
play g4 f e,
|
||||||
|
|
||||||
|
sim (d5 den) (g2 g3 b4),
|
||||||
|
play f4 e d,
|
||||||
|
|
||||||
|
sim (c5 den) (a2 e3 a3),
|
||||||
|
play e4 d c,
|
||||||
|
|
||||||
|
sim (b4 en) (e2 e3 e4),
|
||||||
|
play (e4 e5 e4 e4 e5 e6 d#5 e5 d#5 e5 en),
|
||||||
|
|
||||||
|
play d# e d# e d#,
|
||||||
|
play e d# e b4 d c,
|
||||||
|
|
||||||
|
call subsection1,
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
( sim (a4 en) (a2 e3 a3)
|
||||||
|
, play (b4 c5 d5)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
section1 1,
|
||||||
|
section1 2,
|
||||||
|
section2 1,
|
21
examples/noises.mq
Normal file
21
examples/noises.mq
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
hand1_pool := (
|
||||||
|
chord g#3 g4,
|
||||||
|
chord d#3 d4,
|
||||||
|
chord g3 g#4,
|
||||||
|
chord d3 d#4,
|
||||||
|
),
|
||||||
|
|
||||||
|
hand2_pool := (d8, d#8, g8, g#8, d9, d#9),
|
||||||
|
|
||||||
|
for (up 10) (
|
||||||
|
hand1_length := pick (hn, dhn),
|
||||||
|
say hand1_length,
|
||||||
|
hand1 := (set_len hand1_length (pick hand1_pool)),
|
||||||
|
|
||||||
|
hand2 := (),
|
||||||
|
while (duration hand2 != hand1_length) (
|
||||||
|
hand2 = flat hand2 (set_len (1/64) (pick hand2_pool)),
|
||||||
|
),
|
||||||
|
|
||||||
|
sim hand1 hand2,
|
||||||
|
),
|
13
examples/ode-to-joy.mq
Normal file
13
examples/ode-to-joy.mq
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
C := chord c3 g3 c4,
|
||||||
|
G := chord g3 d4 g4,
|
||||||
|
|
||||||
|
oct 5,
|
||||||
|
par C e e f g,
|
||||||
|
par G g f e d,
|
||||||
|
par C c c d e,
|
||||||
|
par G (e5 (3/8) d5 (1/8) d5 (1/2)),
|
||||||
|
par C e e f g,
|
||||||
|
par G g f e d,
|
||||||
|
par C c c d e,
|
||||||
|
par G (d5 (1/2) c5 (1/8)),
|
||||||
|
par C (c5 1),
|
11
examples/permutations.mq
Normal file
11
examples/permutations.mq
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
factorial := (n | fold '* (1 + up n)),
|
||||||
|
|
||||||
|
|
||||||
|
list_all_permutations := ( array |
|
||||||
|
for (up (factorial (len array))) (|
|
||||||
|
say array,
|
||||||
|
array = permute array,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
list_all_permutations (1 + up 5),
|
6
examples/random-rythm.mq
Normal file
6
examples/random-rythm.mq
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
for (up 10) (n |
|
||||||
|
snd := c + (pick (up 12)),
|
||||||
|
o := if (n % 2 == 0) 3 4,
|
||||||
|
say snd o,
|
||||||
|
play (oct o, snd qn),
|
||||||
|
),
|
40
examples/rhythm-of-primes.mq
Normal file
40
examples/rhythm-of-primes.mq
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
--------------------------------------------------------------
|
||||||
|
Inspired by Marc Evanstein video "The Rythm of The Primes"
|
||||||
|
Link: https://www.youtube.com/watch?v=8x374slJGuo
|
||||||
|
|
||||||
|
This program will iterate over natural numbers, playing chords
|
||||||
|
based on which prime divides given number. This results in
|
||||||
|
following execution:
|
||||||
|
|
||||||
|
step: 2 3 4 5 6 7 8 9 10
|
||||||
|
1 1 1 1 1
|
||||||
|
2 2 2
|
||||||
|
3 3
|
||||||
|
|
||||||
|
where each index corresponds to specific note from scale.
|
||||||
|
Assuming scale [c,d,e] example above would be
|
||||||
|
|
||||||
|
step: 2 3 4 5 6 7 8 9 10
|
||||||
|
c c c c c
|
||||||
|
d d d
|
||||||
|
e e
|
||||||
|
|
||||||
|
which would resolve into:
|
||||||
|
|
||||||
|
play c d c e (c & d) c d (c & e)
|
||||||
|
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
Length := 40,
|
||||||
|
|
||||||
|
cmajor := (c,d,e,f,g),
|
||||||
|
scale := reverse cmajor,
|
||||||
|
primes := nprimes (len scale),
|
||||||
|
indicies := up (len scale),
|
||||||
|
|
||||||
|
oct 3,
|
||||||
|
len (1/16),
|
||||||
|
|
||||||
|
for (2 + up Length) ( i |
|
||||||
|
play (chord scale[indicies[i % primes == 0]]),
|
||||||
|
),
|
13
examples/sandattack.mq
Normal file
13
examples/sandattack.mq
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
bpm 150,
|
||||||
|
len sn,
|
||||||
|
|
||||||
|
play (
|
||||||
|
oct 3, 4 * h, h3 en,
|
||||||
|
oct 3, 6 * h, h3 en,
|
||||||
|
oct 4, 7 * e,
|
||||||
|
oct 4, 6 * d,
|
||||||
|
oct 3, a, a, 5 * h,
|
||||||
|
oct 3, 7 * h,
|
||||||
|
oct 4, 2 * d, 4 * h3, h3 en
|
||||||
|
),
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
var x = 10;
|
|
||||||
say (x + 1)
|
|
164
instruments.mq
Normal file
164
instruments.mq
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
---------------------------------------------------------
|
||||||
|
List of MIDI programs as defined by General MIDI standard.
|
||||||
|
This may be unsupported by your device.
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
-- Piano ------------------------------------------------
|
||||||
|
AcousticGrandPiano := 0,
|
||||||
|
BrightAcousticPiano := 1,
|
||||||
|
ElectricGrandPiano := 2,
|
||||||
|
HonkyTonkPiano := 3,
|
||||||
|
RhodesPiano := 4,
|
||||||
|
ChorusedPiano := 5,
|
||||||
|
Harpsichord := 6,
|
||||||
|
Clavinet := 7,
|
||||||
|
|
||||||
|
-- Chromatic percussion ---------------------------------
|
||||||
|
Celesta := 8,
|
||||||
|
Glockenspiel := 9,
|
||||||
|
MusicBox := 10,
|
||||||
|
Vibraphone := 11,
|
||||||
|
Marimba := 12,
|
||||||
|
Xylophone := 13,
|
||||||
|
TubularBells := 14,
|
||||||
|
Dulcimer := 15,
|
||||||
|
|
||||||
|
-- Organ ------------------------------------------------
|
||||||
|
HammondOrgan := 16,
|
||||||
|
PercussiveOrgan := 17,
|
||||||
|
RockOrgan := 18,
|
||||||
|
ChurchOrgan := 19,
|
||||||
|
ReedOrgan := 20,
|
||||||
|
Accordion := 21,
|
||||||
|
Harmonica := 22,
|
||||||
|
TangoAccordion := 23,
|
||||||
|
|
||||||
|
-- Guitar -----------------------------------------------
|
||||||
|
AcousticGuitarNylon := 24,
|
||||||
|
AcousticGuitarSteel := 25,
|
||||||
|
ElectricGuitarJazz := 26,
|
||||||
|
ElectricGuitarClean := 27,
|
||||||
|
ElectricGuitarMuted := 28,
|
||||||
|
OverdrivenGuitar := 29,
|
||||||
|
DistortionGuitar := 30,
|
||||||
|
GuitarHarmonics := 31,
|
||||||
|
|
||||||
|
-- Bass -------------------------------------------------
|
||||||
|
AcousticBass := 32,
|
||||||
|
ElectricBassFingered := 33,
|
||||||
|
ElectricBassPicked := 34,
|
||||||
|
FretlessBass := 35,
|
||||||
|
SlapBass1 := 36,
|
||||||
|
SlapBass2 := 37,
|
||||||
|
SynthBass1 := 38,
|
||||||
|
SynthBass2 := 39,
|
||||||
|
|
||||||
|
-- Solo strings -----------------------------------------
|
||||||
|
Violin := 40,
|
||||||
|
Viola := 41,
|
||||||
|
Cello := 42,
|
||||||
|
Contrabass := 43,
|
||||||
|
TremoloStrings := 44,
|
||||||
|
PizzicatoStrings := 45,
|
||||||
|
OrchestralHarp := 46,
|
||||||
|
Timpani := 47,
|
||||||
|
|
||||||
|
-- Ensamble ---------------------------------------------
|
||||||
|
StringEnsemble1 := 48,
|
||||||
|
StringEnsemble2 := 49,
|
||||||
|
SynthStrings1 := 50,
|
||||||
|
SynthStrings2 := 51,
|
||||||
|
ChoirAahs := 52,
|
||||||
|
VoiceOohs := 53,
|
||||||
|
SynthVoice := 54,
|
||||||
|
OrchestraHit := 55,
|
||||||
|
|
||||||
|
-- Brass ------------------------------------------------
|
||||||
|
Trumpet := 56,
|
||||||
|
Trombone := 57,
|
||||||
|
Tuba := 58,
|
||||||
|
MutedTrumpet := 59,
|
||||||
|
FrenchHorn := 60,
|
||||||
|
BrassSection := 61,
|
||||||
|
SynthBrass1 := 62,
|
||||||
|
SynthBrass2 := 63,
|
||||||
|
|
||||||
|
-- Reed -------------------------------------------------
|
||||||
|
SopranoSax := 64,
|
||||||
|
AltoSax := 65,
|
||||||
|
TenorSax := 66,
|
||||||
|
BaritoneSax := 67,
|
||||||
|
Oboe := 68,
|
||||||
|
EnglishHorn := 69,
|
||||||
|
Bassoon := 70,
|
||||||
|
Clarinet := 71,
|
||||||
|
|
||||||
|
-- Pipe -------------------------------------------------
|
||||||
|
Piccolo := 72,
|
||||||
|
Flute := 73,
|
||||||
|
Recorder := 74,
|
||||||
|
PanFlute := 75,
|
||||||
|
BlownBottle := 76,
|
||||||
|
Shakuhachi := 77,
|
||||||
|
Whistle := 78,
|
||||||
|
Ocarina := 79,
|
||||||
|
|
||||||
|
-- Synth lead -------------------------------------------
|
||||||
|
Lead1Square := 80,
|
||||||
|
Lead2Sawtooth := 81,
|
||||||
|
Lead3Calliope := 82,
|
||||||
|
Lead4Chiff := 83,
|
||||||
|
Lead5Charang := 84,
|
||||||
|
Lead6Voice := 85,
|
||||||
|
Lead7Fifths := 86,
|
||||||
|
Lead8BassLead := 87,
|
||||||
|
|
||||||
|
-- Synth pad --------------------------------------------
|
||||||
|
Pad1NewAge := 88,
|
||||||
|
Pad2Warm := 89,
|
||||||
|
Pad3Polysynth := 90,
|
||||||
|
Pad4Choir := 91,
|
||||||
|
Pad5Bowed := 92,
|
||||||
|
Pad6Metallic := 93,
|
||||||
|
Pad7Halo := 94,
|
||||||
|
Pad8Sweep := 95,
|
||||||
|
|
||||||
|
-- Synth effects ----------------------------------------
|
||||||
|
FX1Train := 96,
|
||||||
|
FX2Soundtrack := 97,
|
||||||
|
FX3Crystal := 98,
|
||||||
|
FX4Atmosphere := 99,
|
||||||
|
FX5Brightness := 100,
|
||||||
|
FX6Goblins := 101,
|
||||||
|
FX7Echoes := 102,
|
||||||
|
FX8SciFi := 103,
|
||||||
|
|
||||||
|
-- Ethnic -----------------------------------------------
|
||||||
|
Sitar := 104,
|
||||||
|
Banjo := 105,
|
||||||
|
Shamisen := 106,
|
||||||
|
Koto := 107,
|
||||||
|
Kalimba := 108,
|
||||||
|
Bagpipe := 109,
|
||||||
|
Fiddle := 110,
|
||||||
|
Shanai := 111,
|
||||||
|
|
||||||
|
-- Percussive -------------------------------------------
|
||||||
|
TinkleBell := 112,
|
||||||
|
Agogo := 113,
|
||||||
|
SteelDrums := 114,
|
||||||
|
Woodblock := 115,
|
||||||
|
TaikoDrum := 116,
|
||||||
|
MelodicDrum := 117,
|
||||||
|
SynthDrum := 118,
|
||||||
|
ReverseCymbal := 119,
|
||||||
|
|
||||||
|
-- Sound effects ----------------------------------------
|
||||||
|
GuitarFretNoise := 120,
|
||||||
|
BreathNoise := 121,
|
||||||
|
Seashore := 122,
|
||||||
|
BirdTweet := 123,
|
||||||
|
TelephoneRing := 124,
|
||||||
|
Helicopter := 125,
|
||||||
|
Applause := 126,
|
||||||
|
Gunshot := 127,
|
4
lib/asio/COPYING
Normal file
4
lib/asio/COPYING
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
|
||||||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
2
lib/asio/include/.gitignore
vendored
Normal file
2
lib/asio/include/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
658
lib/asio/include/Makefile.am
Normal file
658
lib/asio/include/Makefile.am
Normal file
@ -0,0 +1,658 @@
|
|||||||
|
# find . -name "*.*pp" | sed -e 's/^\.\///' | sed -e 's/^.*$/ & \\/' | sort
|
||||||
|
nobase_include_HEADERS = \
|
||||||
|
asio/any_io_executor.hpp \
|
||||||
|
asio/associated_allocator.hpp \
|
||||||
|
asio/associated_cancellation_slot.hpp \
|
||||||
|
asio/associated_executor.hpp \
|
||||||
|
asio/associator.hpp \
|
||||||
|
asio/async_result.hpp \
|
||||||
|
asio/awaitable.hpp \
|
||||||
|
asio/basic_datagram_socket.hpp \
|
||||||
|
asio/basic_deadline_timer.hpp \
|
||||||
|
asio/basic_file.hpp \
|
||||||
|
asio/basic_io_object.hpp \
|
||||||
|
asio/basic_random_access_file.hpp \
|
||||||
|
asio/basic_raw_socket.hpp \
|
||||||
|
asio/basic_readable_pipe.hpp \
|
||||||
|
asio/basic_seq_packet_socket.hpp \
|
||||||
|
asio/basic_serial_port.hpp \
|
||||||
|
asio/basic_signal_set.hpp \
|
||||||
|
asio/basic_socket_acceptor.hpp \
|
||||||
|
asio/basic_socket.hpp \
|
||||||
|
asio/basic_socket_iostream.hpp \
|
||||||
|
asio/basic_socket_streambuf.hpp \
|
||||||
|
asio/basic_streambuf_fwd.hpp \
|
||||||
|
asio/basic_streambuf.hpp \
|
||||||
|
asio/basic_stream_file.hpp \
|
||||||
|
asio/basic_stream_socket.hpp \
|
||||||
|
asio/basic_waitable_timer.hpp \
|
||||||
|
asio/basic_writable_pipe.hpp \
|
||||||
|
asio/bind_allocator.hpp \
|
||||||
|
asio/bind_cancellation_slot.hpp \
|
||||||
|
asio/bind_executor.hpp \
|
||||||
|
asio/buffered_read_stream_fwd.hpp \
|
||||||
|
asio/buffered_read_stream.hpp \
|
||||||
|
asio/buffered_stream_fwd.hpp \
|
||||||
|
asio/buffered_stream.hpp \
|
||||||
|
asio/buffered_write_stream_fwd.hpp \
|
||||||
|
asio/buffered_write_stream.hpp \
|
||||||
|
asio/buffer.hpp \
|
||||||
|
asio/buffer_registration.hpp \
|
||||||
|
asio/buffers_iterator.hpp \
|
||||||
|
asio/cancellation_signal.hpp \
|
||||||
|
asio/cancellation_state.hpp \
|
||||||
|
asio/cancellation_type.hpp \
|
||||||
|
asio/co_spawn.hpp \
|
||||||
|
asio/completion_condition.hpp \
|
||||||
|
asio/compose.hpp \
|
||||||
|
asio/connect.hpp \
|
||||||
|
asio/connect_pipe.hpp \
|
||||||
|
asio/coroutine.hpp \
|
||||||
|
asio/deadline_timer.hpp \
|
||||||
|
asio/defer.hpp \
|
||||||
|
asio/detached.hpp \
|
||||||
|
asio/detail/array_fwd.hpp \
|
||||||
|
asio/detail/array.hpp \
|
||||||
|
asio/detail/assert.hpp \
|
||||||
|
asio/detail/atomic_count.hpp \
|
||||||
|
asio/detail/base_from_cancellation_state.hpp \
|
||||||
|
asio/detail/base_from_completion_cond.hpp \
|
||||||
|
asio/detail/bind_handler.hpp \
|
||||||
|
asio/detail/blocking_executor_op.hpp \
|
||||||
|
asio/detail/buffered_stream_storage.hpp \
|
||||||
|
asio/detail/buffer_resize_guard.hpp \
|
||||||
|
asio/detail/buffer_sequence_adapter.hpp \
|
||||||
|
asio/detail/bulk_executor_op.hpp \
|
||||||
|
asio/detail/call_stack.hpp \
|
||||||
|
asio/detail/chrono.hpp \
|
||||||
|
asio/detail/chrono_time_traits.hpp \
|
||||||
|
asio/detail/completion_handler.hpp \
|
||||||
|
asio/detail/concurrency_hint.hpp \
|
||||||
|
asio/detail/conditionally_enabled_event.hpp \
|
||||||
|
asio/detail/conditionally_enabled_mutex.hpp \
|
||||||
|
asio/detail/config.hpp \
|
||||||
|
asio/detail/consuming_buffers.hpp \
|
||||||
|
asio/detail/cstddef.hpp \
|
||||||
|
asio/detail/cstdint.hpp \
|
||||||
|
asio/detail/date_time_fwd.hpp \
|
||||||
|
asio/detail/deadline_timer_service.hpp \
|
||||||
|
asio/detail/dependent_type.hpp \
|
||||||
|
asio/detail/descriptor_ops.hpp \
|
||||||
|
asio/detail/descriptor_read_op.hpp \
|
||||||
|
asio/detail/descriptor_write_op.hpp \
|
||||||
|
asio/detail/dev_poll_reactor.hpp \
|
||||||
|
asio/detail/epoll_reactor.hpp \
|
||||||
|
asio/detail/eventfd_select_interrupter.hpp \
|
||||||
|
asio/detail/event.hpp \
|
||||||
|
asio/detail/executor_function.hpp \
|
||||||
|
asio/detail/executor_op.hpp \
|
||||||
|
asio/detail/fd_set_adapter.hpp \
|
||||||
|
asio/detail/fenced_block.hpp \
|
||||||
|
asio/detail/functional.hpp \
|
||||||
|
asio/detail/future.hpp \
|
||||||
|
asio/detail/gcc_arm_fenced_block.hpp \
|
||||||
|
asio/detail/gcc_hppa_fenced_block.hpp \
|
||||||
|
asio/detail/gcc_sync_fenced_block.hpp \
|
||||||
|
asio/detail/gcc_x86_fenced_block.hpp \
|
||||||
|
asio/detail/global.hpp \
|
||||||
|
asio/detail/handler_alloc_helpers.hpp \
|
||||||
|
asio/detail/handler_cont_helpers.hpp \
|
||||||
|
asio/detail/handler_invoke_helpers.hpp \
|
||||||
|
asio/detail/handler_tracking.hpp \
|
||||||
|
asio/detail/handler_type_requirements.hpp \
|
||||||
|
asio/detail/handler_work.hpp \
|
||||||
|
asio/detail/hash_map.hpp \
|
||||||
|
asio/detail/impl/buffer_sequence_adapter.ipp \
|
||||||
|
asio/detail/impl/descriptor_ops.ipp \
|
||||||
|
asio/detail/impl/dev_poll_reactor.hpp \
|
||||||
|
asio/detail/impl/dev_poll_reactor.ipp \
|
||||||
|
asio/detail/impl/epoll_reactor.hpp \
|
||||||
|
asio/detail/impl/epoll_reactor.ipp \
|
||||||
|
asio/detail/impl/eventfd_select_interrupter.ipp \
|
||||||
|
asio/detail/impl/handler_tracking.ipp \
|
||||||
|
asio/detail/impl/io_uring_descriptor_service.ipp \
|
||||||
|
asio/detail/impl/io_uring_file_service.ipp \
|
||||||
|
asio/detail/impl/io_uring_service.hpp \
|
||||||
|
asio/detail/impl/io_uring_service.ipp \
|
||||||
|
asio/detail/impl/io_uring_socket_service_base.ipp \
|
||||||
|
asio/detail/impl/kqueue_reactor.hpp \
|
||||||
|
asio/detail/impl/kqueue_reactor.ipp \
|
||||||
|
asio/detail/impl/null_event.ipp \
|
||||||
|
asio/detail/impl/pipe_select_interrupter.ipp \
|
||||||
|
asio/detail/impl/posix_event.ipp \
|
||||||
|
asio/detail/impl/posix_mutex.ipp \
|
||||||
|
asio/detail/impl/posix_serial_port_service.ipp \
|
||||||
|
asio/detail/impl/posix_thread.ipp \
|
||||||
|
asio/detail/impl/posix_tss_ptr.ipp \
|
||||||
|
asio/detail/impl/reactive_descriptor_service.ipp \
|
||||||
|
asio/detail/impl/reactive_socket_service_base.ipp \
|
||||||
|
asio/detail/impl/resolver_service_base.ipp \
|
||||||
|
asio/detail/impl/scheduler.ipp \
|
||||||
|
asio/detail/impl/select_reactor.hpp \
|
||||||
|
asio/detail/impl/select_reactor.ipp \
|
||||||
|
asio/detail/impl/service_registry.hpp \
|
||||||
|
asio/detail/impl/service_registry.ipp \
|
||||||
|
asio/detail/impl/signal_set_service.ipp \
|
||||||
|
asio/detail/impl/socket_ops.ipp \
|
||||||
|
asio/detail/impl/socket_select_interrupter.ipp \
|
||||||
|
asio/detail/impl/strand_executor_service.hpp \
|
||||||
|
asio/detail/impl/strand_executor_service.ipp \
|
||||||
|
asio/detail/impl/strand_service.hpp \
|
||||||
|
asio/detail/impl/strand_service.ipp \
|
||||||
|
asio/detail/impl/thread_context.ipp \
|
||||||
|
asio/detail/impl/throw_error.ipp \
|
||||||
|
asio/detail/impl/timer_queue_ptime.ipp \
|
||||||
|
asio/detail/impl/timer_queue_set.ipp \
|
||||||
|
asio/detail/impl/win_event.ipp \
|
||||||
|
asio/detail/impl/win_iocp_file_service.ipp \
|
||||||
|
asio/detail/impl/win_iocp_handle_service.ipp \
|
||||||
|
asio/detail/impl/win_iocp_io_context.hpp \
|
||||||
|
asio/detail/impl/win_iocp_io_context.ipp \
|
||||||
|
asio/detail/impl/win_iocp_serial_port_service.ipp \
|
||||||
|
asio/detail/impl/win_iocp_socket_service_base.ipp \
|
||||||
|
asio/detail/impl/win_mutex.ipp \
|
||||||
|
asio/detail/impl/win_object_handle_service.ipp \
|
||||||
|
asio/detail/impl/winrt_ssocket_service_base.ipp \
|
||||||
|
asio/detail/impl/winrt_timer_scheduler.hpp \
|
||||||
|
asio/detail/impl/winrt_timer_scheduler.ipp \
|
||||||
|
asio/detail/impl/winsock_init.ipp \
|
||||||
|
asio/detail/impl/win_static_mutex.ipp \
|
||||||
|
asio/detail/impl/win_thread.ipp \
|
||||||
|
asio/detail/impl/win_tss_ptr.ipp \
|
||||||
|
asio/detail/io_control.hpp \
|
||||||
|
asio/detail/io_object_impl.hpp \
|
||||||
|
asio/detail/io_uring_descriptor_read_at_op.hpp \
|
||||||
|
asio/detail/io_uring_descriptor_read_op.hpp \
|
||||||
|
asio/detail/io_uring_descriptor_service.hpp \
|
||||||
|
asio/detail/io_uring_descriptor_write_at_op.hpp \
|
||||||
|
asio/detail/io_uring_descriptor_write_op.hpp \
|
||||||
|
asio/detail/io_uring_file_service.hpp \
|
||||||
|
asio/detail/io_uring_null_buffers_op.hpp \
|
||||||
|
asio/detail/io_uring_operation.hpp \
|
||||||
|
asio/detail/io_uring_service.hpp \
|
||||||
|
asio/detail/io_uring_socket_accept_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_connect_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_recvfrom_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_recvmsg_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_recv_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_send_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_sendto_op.hpp \
|
||||||
|
asio/detail/io_uring_socket_service_base.hpp \
|
||||||
|
asio/detail/io_uring_socket_service.hpp \
|
||||||
|
asio/detail/io_uring_wait_op.hpp \
|
||||||
|
asio/detail/is_buffer_sequence.hpp \
|
||||||
|
asio/detail/is_executor.hpp \
|
||||||
|
asio/detail/keyword_tss_ptr.hpp \
|
||||||
|
asio/detail/kqueue_reactor.hpp \
|
||||||
|
asio/detail/limits.hpp \
|
||||||
|
asio/detail/local_free_on_block_exit.hpp \
|
||||||
|
asio/detail/macos_fenced_block.hpp \
|
||||||
|
asio/detail/memory.hpp \
|
||||||
|
asio/detail/mutex.hpp \
|
||||||
|
asio/detail/non_const_lvalue.hpp \
|
||||||
|
asio/detail/noncopyable.hpp \
|
||||||
|
asio/detail/null_event.hpp \
|
||||||
|
asio/detail/null_fenced_block.hpp \
|
||||||
|
asio/detail/null_global.hpp \
|
||||||
|
asio/detail/null_mutex.hpp \
|
||||||
|
asio/detail/null_reactor.hpp \
|
||||||
|
asio/detail/null_signal_blocker.hpp \
|
||||||
|
asio/detail/null_socket_service.hpp \
|
||||||
|
asio/detail/null_static_mutex.hpp \
|
||||||
|
asio/detail/null_thread.hpp \
|
||||||
|
asio/detail/null_tss_ptr.hpp \
|
||||||
|
asio/detail/object_pool.hpp \
|
||||||
|
asio/detail/old_win_sdk_compat.hpp \
|
||||||
|
asio/detail/operation.hpp \
|
||||||
|
asio/detail/op_queue.hpp \
|
||||||
|
asio/detail/pipe_select_interrupter.hpp \
|
||||||
|
asio/detail/pop_options.hpp \
|
||||||
|
asio/detail/posix_event.hpp \
|
||||||
|
asio/detail/posix_fd_set_adapter.hpp \
|
||||||
|
asio/detail/posix_global.hpp \
|
||||||
|
asio/detail/posix_mutex.hpp \
|
||||||
|
asio/detail/posix_serial_port_service.hpp \
|
||||||
|
asio/detail/posix_signal_blocker.hpp \
|
||||||
|
asio/detail/posix_static_mutex.hpp \
|
||||||
|
asio/detail/posix_thread.hpp \
|
||||||
|
asio/detail/posix_tss_ptr.hpp \
|
||||||
|
asio/detail/push_options.hpp \
|
||||||
|
asio/detail/reactive_descriptor_service.hpp \
|
||||||
|
asio/detail/reactive_null_buffers_op.hpp \
|
||||||
|
asio/detail/reactive_socket_accept_op.hpp \
|
||||||
|
asio/detail/reactive_socket_connect_op.hpp \
|
||||||
|
asio/detail/reactive_socket_recvfrom_op.hpp \
|
||||||
|
asio/detail/reactive_socket_recvmsg_op.hpp \
|
||||||
|
asio/detail/reactive_socket_recv_op.hpp \
|
||||||
|
asio/detail/reactive_socket_send_op.hpp \
|
||||||
|
asio/detail/reactive_socket_sendto_op.hpp \
|
||||||
|
asio/detail/reactive_socket_service_base.hpp \
|
||||||
|
asio/detail/reactive_socket_service.hpp \
|
||||||
|
asio/detail/reactive_wait_op.hpp \
|
||||||
|
asio/detail/reactor.hpp \
|
||||||
|
asio/detail/reactor_op.hpp \
|
||||||
|
asio/detail/reactor_op_queue.hpp \
|
||||||
|
asio/detail/recycling_allocator.hpp \
|
||||||
|
asio/detail/regex_fwd.hpp \
|
||||||
|
asio/detail/resolve_endpoint_op.hpp \
|
||||||
|
asio/detail/resolve_op.hpp \
|
||||||
|
asio/detail/resolve_query_op.hpp \
|
||||||
|
asio/detail/resolver_service_base.hpp \
|
||||||
|
asio/detail/resolver_service.hpp \
|
||||||
|
asio/detail/scheduler.hpp \
|
||||||
|
asio/detail/scheduler_operation.hpp \
|
||||||
|
asio/detail/scheduler_task.hpp \
|
||||||
|
asio/detail/scheduler_thread_info.hpp \
|
||||||
|
asio/detail/scoped_lock.hpp \
|
||||||
|
asio/detail/scoped_ptr.hpp \
|
||||||
|
asio/detail/select_interrupter.hpp \
|
||||||
|
asio/detail/select_reactor.hpp \
|
||||||
|
asio/detail/service_registry.hpp \
|
||||||
|
asio/detail/signal_blocker.hpp \
|
||||||
|
asio/detail/signal_handler.hpp \
|
||||||
|
asio/detail/signal_init.hpp \
|
||||||
|
asio/detail/signal_op.hpp \
|
||||||
|
asio/detail/signal_set_service.hpp \
|
||||||
|
asio/detail/socket_holder.hpp \
|
||||||
|
asio/detail/socket_ops.hpp \
|
||||||
|
asio/detail/socket_option.hpp \
|
||||||
|
asio/detail/socket_select_interrupter.hpp \
|
||||||
|
asio/detail/socket_types.hpp \
|
||||||
|
asio/detail/solaris_fenced_block.hpp \
|
||||||
|
asio/detail/source_location.hpp \
|
||||||
|
asio/detail/static_mutex.hpp \
|
||||||
|
asio/detail/std_event.hpp \
|
||||||
|
asio/detail/std_fenced_block.hpp \
|
||||||
|
asio/detail/std_global.hpp \
|
||||||
|
asio/detail/std_mutex.hpp \
|
||||||
|
asio/detail/std_static_mutex.hpp \
|
||||||
|
asio/detail/std_thread.hpp \
|
||||||
|
asio/detail/strand_executor_service.hpp \
|
||||||
|
asio/detail/strand_service.hpp \
|
||||||
|
asio/detail/string_view.hpp \
|
||||||
|
asio/detail/thread_context.hpp \
|
||||||
|
asio/detail/thread_group.hpp \
|
||||||
|
asio/detail/thread.hpp \
|
||||||
|
asio/detail/thread_info_base.hpp \
|
||||||
|
asio/detail/throw_error.hpp \
|
||||||
|
asio/detail/throw_exception.hpp \
|
||||||
|
asio/detail/timer_queue_base.hpp \
|
||||||
|
asio/detail/timer_queue.hpp \
|
||||||
|
asio/detail/timer_queue_ptime.hpp \
|
||||||
|
asio/detail/timer_queue_set.hpp \
|
||||||
|
asio/detail/timer_scheduler_fwd.hpp \
|
||||||
|
asio/detail/timer_scheduler.hpp \
|
||||||
|
asio/detail/tss_ptr.hpp \
|
||||||
|
asio/detail/type_traits.hpp \
|
||||||
|
asio/detail/variadic_templates.hpp \
|
||||||
|
asio/detail/wait_handler.hpp \
|
||||||
|
asio/detail/wait_op.hpp \
|
||||||
|
asio/detail/winapp_thread.hpp \
|
||||||
|
asio/detail/wince_thread.hpp \
|
||||||
|
asio/detail/win_event.hpp \
|
||||||
|
asio/detail/win_fd_set_adapter.hpp \
|
||||||
|
asio/detail/win_fenced_block.hpp \
|
||||||
|
asio/detail/win_global.hpp \
|
||||||
|
asio/detail/win_iocp_file_service.hpp \
|
||||||
|
asio/detail/win_iocp_handle_read_op.hpp \
|
||||||
|
asio/detail/win_iocp_handle_service.hpp \
|
||||||
|
asio/detail/win_iocp_handle_write_op.hpp \
|
||||||
|
asio/detail/win_iocp_io_context.hpp \
|
||||||
|
asio/detail/win_iocp_null_buffers_op.hpp \
|
||||||
|
asio/detail/win_iocp_operation.hpp \
|
||||||
|
asio/detail/win_iocp_overlapped_op.hpp \
|
||||||
|
asio/detail/win_iocp_overlapped_ptr.hpp \
|
||||||
|
asio/detail/win_iocp_serial_port_service.hpp \
|
||||||
|
asio/detail/win_iocp_socket_accept_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_connect_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_recvfrom_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_recvmsg_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_recv_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_send_op.hpp \
|
||||||
|
asio/detail/win_iocp_socket_service_base.hpp \
|
||||||
|
asio/detail/win_iocp_socket_service.hpp \
|
||||||
|
asio/detail/win_iocp_thread_info.hpp \
|
||||||
|
asio/detail/win_iocp_wait_op.hpp \
|
||||||
|
asio/detail/win_mutex.hpp \
|
||||||
|
asio/detail/win_object_handle_service.hpp \
|
||||||
|
asio/detail/winrt_async_manager.hpp \
|
||||||
|
asio/detail/winrt_async_op.hpp \
|
||||||
|
asio/detail/winrt_resolve_op.hpp \
|
||||||
|
asio/detail/winrt_resolver_service.hpp \
|
||||||
|
asio/detail/winrt_socket_connect_op.hpp \
|
||||||
|
asio/detail/winrt_socket_recv_op.hpp \
|
||||||
|
asio/detail/winrt_socket_send_op.hpp \
|
||||||
|
asio/detail/winrt_ssocket_service_base.hpp \
|
||||||
|
asio/detail/winrt_ssocket_service.hpp \
|
||||||
|
asio/detail/winrt_timer_scheduler.hpp \
|
||||||
|
asio/detail/winrt_utils.hpp \
|
||||||
|
asio/detail/winsock_init.hpp \
|
||||||
|
asio/detail/win_static_mutex.hpp \
|
||||||
|
asio/detail/win_thread.hpp \
|
||||||
|
asio/detail/win_tss_ptr.hpp \
|
||||||
|
asio/detail/work_dispatcher.hpp \
|
||||||
|
asio/detail/wrapped_handler.hpp \
|
||||||
|
asio/dispatch.hpp \
|
||||||
|
asio/error_code.hpp \
|
||||||
|
asio/error.hpp \
|
||||||
|
asio/execution.hpp \
|
||||||
|
asio/execution_context.hpp \
|
||||||
|
asio/execution/allocator.hpp \
|
||||||
|
asio/execution/any_executor.hpp \
|
||||||
|
asio/execution/bad_executor.hpp \
|
||||||
|
asio/execution/blocking.hpp \
|
||||||
|
asio/execution/blocking_adaptation.hpp \
|
||||||
|
asio/execution/bulk_execute.hpp \
|
||||||
|
asio/execution/bulk_guarantee.hpp \
|
||||||
|
asio/execution/connect.hpp \
|
||||||
|
asio/execution/context.hpp \
|
||||||
|
asio/execution/context_as.hpp \
|
||||||
|
asio/execution/detail/as_invocable.hpp \
|
||||||
|
asio/execution/detail/as_operation.hpp \
|
||||||
|
asio/execution/detail/as_receiver.hpp \
|
||||||
|
asio/execution/detail/bulk_sender.hpp \
|
||||||
|
asio/execution/detail/submit_receiver.hpp \
|
||||||
|
asio/execution/detail/void_receiver.hpp \
|
||||||
|
asio/execution/execute.hpp \
|
||||||
|
asio/execution/executor.hpp \
|
||||||
|
asio/execution/impl/bad_executor.ipp \
|
||||||
|
asio/execution/impl/receiver_invocation_error.ipp \
|
||||||
|
asio/execution/invocable_archetype.hpp \
|
||||||
|
asio/execution/mapping.hpp \
|
||||||
|
asio/execution/occupancy.hpp \
|
||||||
|
asio/execution/operation_state.hpp \
|
||||||
|
asio/execution/outstanding_work.hpp \
|
||||||
|
asio/execution/prefer_only.hpp \
|
||||||
|
asio/execution/receiver.hpp \
|
||||||
|
asio/execution/receiver_invocation_error.hpp \
|
||||||
|
asio/execution/relationship.hpp \
|
||||||
|
asio/execution/schedule.hpp \
|
||||||
|
asio/execution/scheduler.hpp \
|
||||||
|
asio/execution/sender.hpp \
|
||||||
|
asio/execution/set_done.hpp \
|
||||||
|
asio/execution/set_error.hpp \
|
||||||
|
asio/execution/set_value.hpp \
|
||||||
|
asio/execution/start.hpp \
|
||||||
|
asio/execution/submit.hpp \
|
||||||
|
asio/executor.hpp \
|
||||||
|
asio/executor_work_guard.hpp \
|
||||||
|
asio/experimental/append.hpp \
|
||||||
|
asio/experimental/as_single.hpp \
|
||||||
|
asio/experimental/as_tuple.hpp \
|
||||||
|
asio/experimental/awaitable_operators.hpp \
|
||||||
|
asio/experimental/basic_channel.hpp \
|
||||||
|
asio/experimental/basic_concurrent_channel.hpp \
|
||||||
|
asio/experimental/cancellation_condition.hpp \
|
||||||
|
asio/experimental/channel.hpp \
|
||||||
|
asio/experimental/channel_error.hpp \
|
||||||
|
asio/experimental/channel_traits.hpp \
|
||||||
|
asio/experimental/co_spawn.hpp \
|
||||||
|
asio/experimental/concurrent_channel.hpp \
|
||||||
|
asio/experimental/coro.hpp \
|
||||||
|
asio/experimental/coro_traits.hpp \
|
||||||
|
asio/experimental/deferred.hpp \
|
||||||
|
asio/experimental/detail/channel_handler.hpp \
|
||||||
|
asio/experimental/detail/channel_message.hpp \
|
||||||
|
asio/experimental/detail/channel_operation.hpp \
|
||||||
|
asio/experimental/detail/channel_payload.hpp \
|
||||||
|
asio/experimental/detail/channel_receive_op.hpp \
|
||||||
|
asio/experimental/detail/channel_send_functions.hpp \
|
||||||
|
asio/experimental/detail/channel_send_op.hpp \
|
||||||
|
asio/experimental/detail/channel_service.hpp \
|
||||||
|
asio/experimental/detail/completion_handler_erasure.hpp \
|
||||||
|
asio/experimental/detail/coro_promise_allocator.hpp \
|
||||||
|
asio/experimental/detail/has_signature.hpp \
|
||||||
|
asio/experimental/detail/impl/channel_service.hpp \
|
||||||
|
asio/experimental/detail/partial_promise.hpp \
|
||||||
|
asio/experimental/impl/append.hpp \
|
||||||
|
asio/experimental/impl/as_single.hpp \
|
||||||
|
asio/experimental/impl/as_tuple.hpp \
|
||||||
|
asio/experimental/impl/channel_error.ipp \
|
||||||
|
asio/experimental/impl/coro.hpp \
|
||||||
|
asio/experimental/impl/deferred.hpp \
|
||||||
|
asio/experimental/impl/parallel_group.hpp \
|
||||||
|
asio/experimental/impl/prepend.hpp \
|
||||||
|
asio/experimental/impl/promise.hpp \
|
||||||
|
asio/experimental/impl/use_coro.hpp \
|
||||||
|
asio/experimental/parallel_group.hpp \
|
||||||
|
asio/experimental/prepend.hpp \
|
||||||
|
asio/experimental/promise.hpp \
|
||||||
|
asio/experimental/use_coro.hpp \
|
||||||
|
asio/file_base.hpp \
|
||||||
|
asio/generic/basic_endpoint.hpp \
|
||||||
|
asio/generic/datagram_protocol.hpp \
|
||||||
|
asio/generic/detail/endpoint.hpp \
|
||||||
|
asio/generic/detail/impl/endpoint.ipp \
|
||||||
|
asio/generic/raw_protocol.hpp \
|
||||||
|
asio/generic/seq_packet_protocol.hpp \
|
||||||
|
asio/generic/stream_protocol.hpp \
|
||||||
|
asio/handler_alloc_hook.hpp \
|
||||||
|
asio/handler_continuation_hook.hpp \
|
||||||
|
asio/handler_invoke_hook.hpp \
|
||||||
|
asio/high_resolution_timer.hpp \
|
||||||
|
asio.hpp \
|
||||||
|
asio/impl/any_io_executor.ipp \
|
||||||
|
asio/impl/awaitable.hpp \
|
||||||
|
asio/impl/buffered_read_stream.hpp \
|
||||||
|
asio/impl/buffered_write_stream.hpp \
|
||||||
|
asio/impl/cancellation_signal.ipp \
|
||||||
|
asio/impl/co_spawn.hpp \
|
||||||
|
asio/impl/compose.hpp \
|
||||||
|
asio/impl/connect.hpp \
|
||||||
|
asio/impl/connect_pipe.hpp \
|
||||||
|
asio/impl/connect_pipe.ipp \
|
||||||
|
asio/impl/defer.hpp \
|
||||||
|
asio/impl/detached.hpp \
|
||||||
|
asio/impl/dispatch.hpp \
|
||||||
|
asio/impl/error_code.ipp \
|
||||||
|
asio/impl/error.ipp \
|
||||||
|
asio/impl/execution_context.hpp \
|
||||||
|
asio/impl/execution_context.ipp \
|
||||||
|
asio/impl/executor.hpp \
|
||||||
|
asio/impl/executor.ipp \
|
||||||
|
asio/impl/handler_alloc_hook.ipp \
|
||||||
|
asio/impl/io_context.hpp \
|
||||||
|
asio/impl/io_context.ipp \
|
||||||
|
asio/impl/multiple_exceptions.ipp \
|
||||||
|
asio/impl/post.hpp \
|
||||||
|
asio/impl/read_at.hpp \
|
||||||
|
asio/impl/read.hpp \
|
||||||
|
asio/impl/read_until.hpp \
|
||||||
|
asio/impl/redirect_error.hpp \
|
||||||
|
asio/impl/serial_port_base.hpp \
|
||||||
|
asio/impl/serial_port_base.ipp \
|
||||||
|
asio/impl/spawn.hpp \
|
||||||
|
asio/impl/src.hpp \
|
||||||
|
asio/impl/system_context.hpp \
|
||||||
|
asio/impl/system_context.ipp \
|
||||||
|
asio/impl/system_executor.hpp \
|
||||||
|
asio/impl/thread_pool.hpp \
|
||||||
|
asio/impl/thread_pool.ipp \
|
||||||
|
asio/impl/use_awaitable.hpp \
|
||||||
|
asio/impl/use_future.hpp \
|
||||||
|
asio/impl/write_at.hpp \
|
||||||
|
asio/impl/write.hpp \
|
||||||
|
asio/io_context.hpp \
|
||||||
|
asio/io_context_strand.hpp \
|
||||||
|
asio/io_service.hpp \
|
||||||
|
asio/io_service_strand.hpp \
|
||||||
|
asio/ip/address.hpp \
|
||||||
|
asio/ip/address_v4.hpp \
|
||||||
|
asio/ip/address_v4_iterator.hpp \
|
||||||
|
asio/ip/address_v4_range.hpp \
|
||||||
|
asio/ip/address_v6.hpp \
|
||||||
|
asio/ip/address_v6_iterator.hpp \
|
||||||
|
asio/ip/address_v6_range.hpp \
|
||||||
|
asio/ip/bad_address_cast.hpp \
|
||||||
|
asio/ip/basic_endpoint.hpp \
|
||||||
|
asio/ip/basic_resolver_entry.hpp \
|
||||||
|
asio/ip/basic_resolver.hpp \
|
||||||
|
asio/ip/basic_resolver_iterator.hpp \
|
||||||
|
asio/ip/basic_resolver_query.hpp \
|
||||||
|
asio/ip/basic_resolver_results.hpp \
|
||||||
|
asio/ip/detail/endpoint.hpp \
|
||||||
|
asio/ip/detail/impl/endpoint.ipp \
|
||||||
|
asio/ip/detail/socket_option.hpp \
|
||||||
|
asio/ip/host_name.hpp \
|
||||||
|
asio/ip/icmp.hpp \
|
||||||
|
asio/ip/impl/address.hpp \
|
||||||
|
asio/ip/impl/address.ipp \
|
||||||
|
asio/ip/impl/address_v4.hpp \
|
||||||
|
asio/ip/impl/address_v4.ipp \
|
||||||
|
asio/ip/impl/address_v6.hpp \
|
||||||
|
asio/ip/impl/address_v6.ipp \
|
||||||
|
asio/ip/impl/basic_endpoint.hpp \
|
||||||
|
asio/ip/impl/host_name.ipp \
|
||||||
|
asio/ip/impl/network_v4.hpp \
|
||||||
|
asio/ip/impl/network_v4.ipp \
|
||||||
|
asio/ip/impl/network_v6.hpp \
|
||||||
|
asio/ip/impl/network_v6.ipp \
|
||||||
|
asio/ip/multicast.hpp \
|
||||||
|
asio/ip/network_v4.hpp \
|
||||||
|
asio/ip/network_v6.hpp \
|
||||||
|
asio/ip/resolver_base.hpp \
|
||||||
|
asio/ip/resolver_query_base.hpp \
|
||||||
|
asio/ip/tcp.hpp \
|
||||||
|
asio/ip/udp.hpp \
|
||||||
|
asio/ip/unicast.hpp \
|
||||||
|
asio/ip/v6_only.hpp \
|
||||||
|
asio/is_applicable_property.hpp \
|
||||||
|
asio/is_executor.hpp \
|
||||||
|
asio/is_read_buffered.hpp \
|
||||||
|
asio/is_write_buffered.hpp \
|
||||||
|
asio/local/basic_endpoint.hpp \
|
||||||
|
asio/local/connect_pair.hpp \
|
||||||
|
asio/local/datagram_protocol.hpp \
|
||||||
|
asio/local/detail/endpoint.hpp \
|
||||||
|
asio/local/detail/impl/endpoint.ipp \
|
||||||
|
asio/local/stream_protocol.hpp \
|
||||||
|
asio/multiple_exceptions.hpp \
|
||||||
|
asio/packaged_task.hpp \
|
||||||
|
asio/placeholders.hpp \
|
||||||
|
asio/posix/basic_descriptor.hpp \
|
||||||
|
asio/posix/basic_stream_descriptor.hpp \
|
||||||
|
asio/posix/descriptor_base.hpp \
|
||||||
|
asio/posix/descriptor.hpp \
|
||||||
|
asio/posix/stream_descriptor.hpp \
|
||||||
|
asio/post.hpp \
|
||||||
|
asio/prefer.hpp \
|
||||||
|
asio/query.hpp \
|
||||||
|
asio/random_access_file.hpp \
|
||||||
|
asio/read_at.hpp \
|
||||||
|
asio/read.hpp \
|
||||||
|
asio/read_until.hpp \
|
||||||
|
asio/readable_pipe.hpp \
|
||||||
|
asio/recycling_allocator.hpp \
|
||||||
|
asio/redirect_error.hpp \
|
||||||
|
asio/registered_buffer.hpp \
|
||||||
|
asio/require.hpp \
|
||||||
|
asio/require_concept.hpp \
|
||||||
|
asio/serial_port_base.hpp \
|
||||||
|
asio/serial_port.hpp \
|
||||||
|
asio/signal_set.hpp \
|
||||||
|
asio/socket_base.hpp \
|
||||||
|
asio/spawn.hpp \
|
||||||
|
asio/ssl/context_base.hpp \
|
||||||
|
asio/ssl/context.hpp \
|
||||||
|
asio/ssl/detail/buffered_handshake_op.hpp \
|
||||||
|
asio/ssl/detail/engine.hpp \
|
||||||
|
asio/ssl/detail/handshake_op.hpp \
|
||||||
|
asio/ssl/detail/impl/engine.ipp \
|
||||||
|
asio/ssl/detail/impl/openssl_init.ipp \
|
||||||
|
asio/ssl/detail/io.hpp \
|
||||||
|
asio/ssl/detail/openssl_init.hpp \
|
||||||
|
asio/ssl/detail/openssl_types.hpp \
|
||||||
|
asio/ssl/detail/password_callback.hpp \
|
||||||
|
asio/ssl/detail/read_op.hpp \
|
||||||
|
asio/ssl/detail/shutdown_op.hpp \
|
||||||
|
asio/ssl/detail/stream_core.hpp \
|
||||||
|
asio/ssl/detail/verify_callback.hpp \
|
||||||
|
asio/ssl/detail/write_op.hpp \
|
||||||
|
asio/ssl/error.hpp \
|
||||||
|
asio/ssl.hpp \
|
||||||
|
asio/ssl/host_name_verification.hpp \
|
||||||
|
asio/ssl/impl/context.hpp \
|
||||||
|
asio/ssl/impl/context.ipp \
|
||||||
|
asio/ssl/impl/error.ipp \
|
||||||
|
asio/ssl/impl/host_name_verification.ipp \
|
||||||
|
asio/ssl/impl/rfc2818_verification.ipp \
|
||||||
|
asio/ssl/impl/src.hpp \
|
||||||
|
asio/ssl/rfc2818_verification.hpp \
|
||||||
|
asio/ssl/stream_base.hpp \
|
||||||
|
asio/ssl/stream.hpp \
|
||||||
|
asio/ssl/verify_context.hpp \
|
||||||
|
asio/ssl/verify_mode.hpp \
|
||||||
|
asio/static_thread_pool.hpp \
|
||||||
|
asio/steady_timer.hpp \
|
||||||
|
asio/strand.hpp \
|
||||||
|
asio/streambuf.hpp \
|
||||||
|
asio/stream_file.hpp \
|
||||||
|
asio/system_context.hpp \
|
||||||
|
asio/system_error.hpp \
|
||||||
|
asio/system_executor.hpp \
|
||||||
|
asio/system_timer.hpp \
|
||||||
|
asio/this_coro.hpp \
|
||||||
|
asio/thread.hpp \
|
||||||
|
asio/thread_pool.hpp \
|
||||||
|
asio/time_traits.hpp \
|
||||||
|
asio/traits/bulk_execute_free.hpp \
|
||||||
|
asio/traits/bulk_execute_member.hpp \
|
||||||
|
asio/traits/connect_free.hpp \
|
||||||
|
asio/traits/connect_member.hpp \
|
||||||
|
asio/traits/equality_comparable.hpp \
|
||||||
|
asio/traits/execute_free.hpp \
|
||||||
|
asio/traits/execute_member.hpp \
|
||||||
|
asio/traits/prefer_free.hpp \
|
||||||
|
asio/traits/prefer_member.hpp \
|
||||||
|
asio/traits/query_free.hpp \
|
||||||
|
asio/traits/query_member.hpp \
|
||||||
|
asio/traits/query_static_constexpr_member.hpp \
|
||||||
|
asio/traits/require_concept_free.hpp \
|
||||||
|
asio/traits/require_concept_member.hpp \
|
||||||
|
asio/traits/require_free.hpp \
|
||||||
|
asio/traits/require_member.hpp \
|
||||||
|
asio/traits/schedule_free.hpp \
|
||||||
|
asio/traits/schedule_member.hpp \
|
||||||
|
asio/traits/set_done_free.hpp \
|
||||||
|
asio/traits/set_done_member.hpp \
|
||||||
|
asio/traits/set_error_free.hpp \
|
||||||
|
asio/traits/set_error_member.hpp \
|
||||||
|
asio/traits/set_value_free.hpp \
|
||||||
|
asio/traits/set_value_member.hpp \
|
||||||
|
asio/traits/start_free.hpp \
|
||||||
|
asio/traits/start_member.hpp \
|
||||||
|
asio/traits/static_query.hpp \
|
||||||
|
asio/traits/static_require.hpp \
|
||||||
|
asio/traits/static_require_concept.hpp \
|
||||||
|
asio/traits/submit_free.hpp \
|
||||||
|
asio/traits/submit_member.hpp \
|
||||||
|
asio/ts/buffer.hpp \
|
||||||
|
asio/ts/executor.hpp \
|
||||||
|
asio/ts/internet.hpp \
|
||||||
|
asio/ts/io_context.hpp \
|
||||||
|
asio/ts/netfwd.hpp \
|
||||||
|
asio/ts/net.hpp \
|
||||||
|
asio/ts/socket.hpp \
|
||||||
|
asio/ts/timer.hpp \
|
||||||
|
asio/unyield.hpp \
|
||||||
|
asio/use_awaitable.hpp \
|
||||||
|
asio/use_future.hpp \
|
||||||
|
asio/uses_executor.hpp \
|
||||||
|
asio/version.hpp \
|
||||||
|
asio/wait_traits.hpp \
|
||||||
|
asio/windows/basic_object_handle.hpp \
|
||||||
|
asio/windows/basic_overlapped_handle.hpp \
|
||||||
|
asio/windows/basic_random_access_handle.hpp \
|
||||||
|
asio/windows/basic_stream_handle.hpp \
|
||||||
|
asio/windows/object_handle.hpp \
|
||||||
|
asio/windows/overlapped_handle.hpp \
|
||||||
|
asio/windows/overlapped_ptr.hpp \
|
||||||
|
asio/windows/random_access_handle.hpp \
|
||||||
|
asio/windows/stream_handle.hpp \
|
||||||
|
asio/writable_pipe.hpp \
|
||||||
|
asio/write_at.hpp \
|
||||||
|
asio/write.hpp \
|
||||||
|
asio/yield.hpp
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = \
|
||||||
|
$(srcdir)/Makefile.in
|
203
lib/asio/include/asio.hpp
Normal file
203
lib/asio/include/asio.hpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
//
|
||||||
|
// asio.hpp
|
||||||
|
// ~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_HPP
|
||||||
|
#define ASIO_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/associated_allocator.hpp"
|
||||||
|
#include "asio/associated_executor.hpp"
|
||||||
|
#include "asio/associated_cancellation_slot.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/awaitable.hpp"
|
||||||
|
#include "asio/basic_datagram_socket.hpp"
|
||||||
|
#include "asio/basic_deadline_timer.hpp"
|
||||||
|
#include "asio/basic_file.hpp"
|
||||||
|
#include "asio/basic_io_object.hpp"
|
||||||
|
#include "asio/basic_random_access_file.hpp"
|
||||||
|
#include "asio/basic_raw_socket.hpp"
|
||||||
|
#include "asio/basic_readable_pipe.hpp"
|
||||||
|
#include "asio/basic_seq_packet_socket.hpp"
|
||||||
|
#include "asio/basic_serial_port.hpp"
|
||||||
|
#include "asio/basic_signal_set.hpp"
|
||||||
|
#include "asio/basic_socket.hpp"
|
||||||
|
#include "asio/basic_socket_acceptor.hpp"
|
||||||
|
#include "asio/basic_socket_iostream.hpp"
|
||||||
|
#include "asio/basic_socket_streambuf.hpp"
|
||||||
|
#include "asio/basic_stream_file.hpp"
|
||||||
|
#include "asio/basic_stream_socket.hpp"
|
||||||
|
#include "asio/basic_streambuf.hpp"
|
||||||
|
#include "asio/basic_waitable_timer.hpp"
|
||||||
|
#include "asio/basic_writable_pipe.hpp"
|
||||||
|
#include "asio/bind_allocator.hpp"
|
||||||
|
#include "asio/bind_cancellation_slot.hpp"
|
||||||
|
#include "asio/bind_executor.hpp"
|
||||||
|
#include "asio/buffer.hpp"
|
||||||
|
#include "asio/buffer_registration.hpp"
|
||||||
|
#include "asio/buffered_read_stream_fwd.hpp"
|
||||||
|
#include "asio/buffered_read_stream.hpp"
|
||||||
|
#include "asio/buffered_stream_fwd.hpp"
|
||||||
|
#include "asio/buffered_stream.hpp"
|
||||||
|
#include "asio/buffered_write_stream_fwd.hpp"
|
||||||
|
#include "asio/buffered_write_stream.hpp"
|
||||||
|
#include "asio/buffers_iterator.hpp"
|
||||||
|
#include "asio/cancellation_signal.hpp"
|
||||||
|
#include "asio/cancellation_state.hpp"
|
||||||
|
#include "asio/cancellation_type.hpp"
|
||||||
|
#include "asio/co_spawn.hpp"
|
||||||
|
#include "asio/completion_condition.hpp"
|
||||||
|
#include "asio/compose.hpp"
|
||||||
|
#include "asio/connect.hpp"
|
||||||
|
#include "asio/connect_pipe.hpp"
|
||||||
|
#include "asio/coroutine.hpp"
|
||||||
|
#include "asio/deadline_timer.hpp"
|
||||||
|
#include "asio/defer.hpp"
|
||||||
|
#include "asio/detached.hpp"
|
||||||
|
#include "asio/dispatch.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/error_code.hpp"
|
||||||
|
#include "asio/execution.hpp"
|
||||||
|
#include "asio/execution/allocator.hpp"
|
||||||
|
#include "asio/execution/any_executor.hpp"
|
||||||
|
#include "asio/execution/blocking.hpp"
|
||||||
|
#include "asio/execution/blocking_adaptation.hpp"
|
||||||
|
#include "asio/execution/bulk_execute.hpp"
|
||||||
|
#include "asio/execution/bulk_guarantee.hpp"
|
||||||
|
#include "asio/execution/connect.hpp"
|
||||||
|
#include "asio/execution/context.hpp"
|
||||||
|
#include "asio/execution/context_as.hpp"
|
||||||
|
#include "asio/execution/execute.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/execution/invocable_archetype.hpp"
|
||||||
|
#include "asio/execution/mapping.hpp"
|
||||||
|
#include "asio/execution/occupancy.hpp"
|
||||||
|
#include "asio/execution/operation_state.hpp"
|
||||||
|
#include "asio/execution/outstanding_work.hpp"
|
||||||
|
#include "asio/execution/prefer_only.hpp"
|
||||||
|
#include "asio/execution/receiver.hpp"
|
||||||
|
#include "asio/execution/receiver_invocation_error.hpp"
|
||||||
|
#include "asio/execution/relationship.hpp"
|
||||||
|
#include "asio/execution/schedule.hpp"
|
||||||
|
#include "asio/execution/scheduler.hpp"
|
||||||
|
#include "asio/execution/sender.hpp"
|
||||||
|
#include "asio/execution/set_done.hpp"
|
||||||
|
#include "asio/execution/set_error.hpp"
|
||||||
|
#include "asio/execution/set_value.hpp"
|
||||||
|
#include "asio/execution/start.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/executor.hpp"
|
||||||
|
#include "asio/executor_work_guard.hpp"
|
||||||
|
#include "asio/file_base.hpp"
|
||||||
|
#include "asio/generic/basic_endpoint.hpp"
|
||||||
|
#include "asio/generic/datagram_protocol.hpp"
|
||||||
|
#include "asio/generic/raw_protocol.hpp"
|
||||||
|
#include "asio/generic/seq_packet_protocol.hpp"
|
||||||
|
#include "asio/generic/stream_protocol.hpp"
|
||||||
|
#include "asio/handler_alloc_hook.hpp"
|
||||||
|
#include "asio/handler_continuation_hook.hpp"
|
||||||
|
#include "asio/handler_invoke_hook.hpp"
|
||||||
|
#include "asio/high_resolution_timer.hpp"
|
||||||
|
#include "asio/io_context.hpp"
|
||||||
|
#include "asio/io_context_strand.hpp"
|
||||||
|
#include "asio/io_service.hpp"
|
||||||
|
#include "asio/io_service_strand.hpp"
|
||||||
|
#include "asio/ip/address.hpp"
|
||||||
|
#include "asio/ip/address_v4.hpp"
|
||||||
|
#include "asio/ip/address_v4_iterator.hpp"
|
||||||
|
#include "asio/ip/address_v4_range.hpp"
|
||||||
|
#include "asio/ip/address_v6.hpp"
|
||||||
|
#include "asio/ip/address_v6_iterator.hpp"
|
||||||
|
#include "asio/ip/address_v6_range.hpp"
|
||||||
|
#include "asio/ip/network_v4.hpp"
|
||||||
|
#include "asio/ip/network_v6.hpp"
|
||||||
|
#include "asio/ip/bad_address_cast.hpp"
|
||||||
|
#include "asio/ip/basic_endpoint.hpp"
|
||||||
|
#include "asio/ip/basic_resolver.hpp"
|
||||||
|
#include "asio/ip/basic_resolver_entry.hpp"
|
||||||
|
#include "asio/ip/basic_resolver_iterator.hpp"
|
||||||
|
#include "asio/ip/basic_resolver_query.hpp"
|
||||||
|
#include "asio/ip/host_name.hpp"
|
||||||
|
#include "asio/ip/icmp.hpp"
|
||||||
|
#include "asio/ip/multicast.hpp"
|
||||||
|
#include "asio/ip/resolver_base.hpp"
|
||||||
|
#include "asio/ip/resolver_query_base.hpp"
|
||||||
|
#include "asio/ip/tcp.hpp"
|
||||||
|
#include "asio/ip/udp.hpp"
|
||||||
|
#include "asio/ip/unicast.hpp"
|
||||||
|
#include "asio/ip/v6_only.hpp"
|
||||||
|
#include "asio/is_applicable_property.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
#include "asio/is_read_buffered.hpp"
|
||||||
|
#include "asio/is_write_buffered.hpp"
|
||||||
|
#include "asio/local/basic_endpoint.hpp"
|
||||||
|
#include "asio/local/connect_pair.hpp"
|
||||||
|
#include "asio/local/datagram_protocol.hpp"
|
||||||
|
#include "asio/local/stream_protocol.hpp"
|
||||||
|
#include "asio/multiple_exceptions.hpp"
|
||||||
|
#include "asio/packaged_task.hpp"
|
||||||
|
#include "asio/placeholders.hpp"
|
||||||
|
#include "asio/posix/basic_descriptor.hpp"
|
||||||
|
#include "asio/posix/basic_stream_descriptor.hpp"
|
||||||
|
#include "asio/posix/descriptor.hpp"
|
||||||
|
#include "asio/posix/descriptor_base.hpp"
|
||||||
|
#include "asio/posix/stream_descriptor.hpp"
|
||||||
|
#include "asio/post.hpp"
|
||||||
|
#include "asio/prefer.hpp"
|
||||||
|
#include "asio/query.hpp"
|
||||||
|
#include "asio/random_access_file.hpp"
|
||||||
|
#include "asio/read.hpp"
|
||||||
|
#include "asio/read_at.hpp"
|
||||||
|
#include "asio/read_until.hpp"
|
||||||
|
#include "asio/readable_pipe.hpp"
|
||||||
|
#include "asio/recycling_allocator.hpp"
|
||||||
|
#include "asio/redirect_error.hpp"
|
||||||
|
#include "asio/registered_buffer.hpp"
|
||||||
|
#include "asio/require.hpp"
|
||||||
|
#include "asio/require_concept.hpp"
|
||||||
|
#include "asio/serial_port.hpp"
|
||||||
|
#include "asio/serial_port_base.hpp"
|
||||||
|
#include "asio/signal_set.hpp"
|
||||||
|
#include "asio/socket_base.hpp"
|
||||||
|
#include "asio/static_thread_pool.hpp"
|
||||||
|
#include "asio/steady_timer.hpp"
|
||||||
|
#include "asio/strand.hpp"
|
||||||
|
#include "asio/stream_file.hpp"
|
||||||
|
#include "asio/streambuf.hpp"
|
||||||
|
#include "asio/system_context.hpp"
|
||||||
|
#include "asio/system_error.hpp"
|
||||||
|
#include "asio/system_executor.hpp"
|
||||||
|
#include "asio/system_timer.hpp"
|
||||||
|
#include "asio/this_coro.hpp"
|
||||||
|
#include "asio/thread.hpp"
|
||||||
|
#include "asio/thread_pool.hpp"
|
||||||
|
#include "asio/time_traits.hpp"
|
||||||
|
#include "asio/use_awaitable.hpp"
|
||||||
|
#include "asio/use_future.hpp"
|
||||||
|
#include "asio/uses_executor.hpp"
|
||||||
|
#include "asio/version.hpp"
|
||||||
|
#include "asio/wait_traits.hpp"
|
||||||
|
#include "asio/windows/basic_object_handle.hpp"
|
||||||
|
#include "asio/windows/basic_overlapped_handle.hpp"
|
||||||
|
#include "asio/windows/basic_random_access_handle.hpp"
|
||||||
|
#include "asio/windows/basic_stream_handle.hpp"
|
||||||
|
#include "asio/windows/object_handle.hpp"
|
||||||
|
#include "asio/windows/overlapped_handle.hpp"
|
||||||
|
#include "asio/windows/overlapped_ptr.hpp"
|
||||||
|
#include "asio/windows/random_access_handle.hpp"
|
||||||
|
#include "asio/windows/stream_handle.hpp"
|
||||||
|
#include "asio/writable_pipe.hpp"
|
||||||
|
#include "asio/write.hpp"
|
||||||
|
#include "asio/write_at.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_HPP
|
303
lib/asio/include/asio/any_io_executor.hpp
Normal file
303
lib/asio/include/asio/any_io_executor.hpp
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
//
|
||||||
|
// any_io_executor.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_ANY_IO_EXECUTOR_HPP
|
||||||
|
#define ASIO_ANY_IO_EXECUTOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
# include "asio/executor.hpp"
|
||||||
|
#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
# include "asio/execution.hpp"
|
||||||
|
# include "asio/execution_context.hpp"
|
||||||
|
#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
|
||||||
|
typedef executor any_io_executor;
|
||||||
|
|
||||||
|
#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
|
||||||
|
/// Polymorphic executor type for use with I/O objects.
|
||||||
|
/**
|
||||||
|
* The @c any_io_executor type is a polymorphic executor that supports the set
|
||||||
|
* of properties required by I/O objects. It is defined as the
|
||||||
|
* execution::any_executor class template parameterised as follows:
|
||||||
|
* @code execution::any_executor<
|
||||||
|
* execution::context_as_t<execution_context&>,
|
||||||
|
* execution::blocking_t::never_t,
|
||||||
|
* execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||||
|
* execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||||
|
* execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||||
|
* execution::prefer_only<execution::relationship_t::fork_t>,
|
||||||
|
* execution::prefer_only<execution::relationship_t::continuation_t>
|
||||||
|
* > @endcode
|
||||||
|
*/
|
||||||
|
class any_io_executor :
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
public execution::any_executor<...>
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
public execution::any_executor<
|
||||||
|
execution::context_as_t<execution_context&>,
|
||||||
|
execution::blocking_t::never_t,
|
||||||
|
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||||
|
>
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef execution::any_executor<
|
||||||
|
execution::context_as_t<execution_context&>,
|
||||||
|
execution::blocking_t::never_t,
|
||||||
|
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||||
|
> base_type;
|
||||||
|
|
||||||
|
typedef void supportable_properties_type(
|
||||||
|
execution::context_as_t<execution_context&>,
|
||||||
|
execution::blocking_t::never_t,
|
||||||
|
execution::prefer_only<execution::blocking_t::possibly_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::tracked_t>,
|
||||||
|
execution::prefer_only<execution::outstanding_work_t::untracked_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::fork_t>,
|
||||||
|
execution::prefer_only<execution::relationship_t::continuation_t>
|
||||||
|
);
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Default constructor.
|
||||||
|
ASIO_DECL any_io_executor() ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
/// Construct in an empty state. Equivalent effects to default constructor.
|
||||||
|
ASIO_DECL any_io_executor(nullptr_t) ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
ASIO_DECL any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move constructor.
|
||||||
|
ASIO_DECL any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT;
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Construct to point to the same target as another any_executor.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <class... OtherSupportableProperties>
|
||||||
|
any_io_executor(execution::any_executor<OtherSupportableProperties...> e);
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename OtherAnyExecutor>
|
||||||
|
any_io_executor(OtherAnyExecutor e,
|
||||||
|
typename constraint<
|
||||||
|
conditional<
|
||||||
|
!is_same<OtherAnyExecutor, any_io_executor>::value
|
||||||
|
&& is_base_of<execution::detail::any_executor_base,
|
||||||
|
OtherAnyExecutor>::value,
|
||||||
|
typename execution::detail::supportable_properties<
|
||||||
|
0, supportable_properties_type>::template
|
||||||
|
is_valid_target<OtherAnyExecutor>,
|
||||||
|
false_type
|
||||||
|
>::type::value
|
||||||
|
>::type = 0)
|
||||||
|
: base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Construct a polymorphic wrapper for the specified executor.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <ASIO_EXECUTION_EXECUTOR Executor>
|
||||||
|
any_io_executor(Executor e);
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <ASIO_EXECUTION_EXECUTOR Executor>
|
||||||
|
any_io_executor(Executor e,
|
||||||
|
typename constraint<
|
||||||
|
conditional<
|
||||||
|
!is_same<Executor, any_io_executor>::value
|
||||||
|
&& !is_base_of<execution::detail::any_executor_base,
|
||||||
|
Executor>::value,
|
||||||
|
execution::detail::is_valid_target_executor<
|
||||||
|
Executor, supportable_properties_type>,
|
||||||
|
false_type
|
||||||
|
>::type::value
|
||||||
|
>::type = 0)
|
||||||
|
: base_type(ASIO_MOVE_CAST(Executor)(e))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Assignment operator.
|
||||||
|
ASIO_DECL any_io_executor& operator=(
|
||||||
|
const any_io_executor& e) ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move assignment operator.
|
||||||
|
ASIO_DECL any_io_executor& operator=(
|
||||||
|
any_io_executor&& e) ASIO_NOEXCEPT;
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Assignment operator that sets the polymorphic wrapper to the empty state.
|
||||||
|
ASIO_DECL any_io_executor& operator=(nullptr_t);
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
ASIO_DECL ~any_io_executor();
|
||||||
|
|
||||||
|
/// Swap targets with another polymorphic wrapper.
|
||||||
|
ASIO_DECL void swap(any_io_executor& other) ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
/// Obtain a polymorphic wrapper with the specified property.
|
||||||
|
/**
|
||||||
|
* Do not call this function directly. It is intended for use with the
|
||||||
|
* asio::require and asio::prefer customisation points.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* @code any_io_executor ex = ...;
|
||||||
|
* auto ex2 = asio::require(ex, execution::blocking.possibly); @endcode
|
||||||
|
*/
|
||||||
|
template <typename Property>
|
||||||
|
any_io_executor require(const Property& p,
|
||||||
|
typename constraint<
|
||||||
|
traits::require_member<const base_type&, const Property&>::is_valid
|
||||||
|
>::type = 0) const
|
||||||
|
{
|
||||||
|
return static_cast<const base_type&>(*this).require(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a polymorphic wrapper with the specified property.
|
||||||
|
/**
|
||||||
|
* Do not call this function directly. It is intended for use with the
|
||||||
|
* asio::prefer customisation point.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* @code any_io_executor ex = ...;
|
||||||
|
* auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode
|
||||||
|
*/
|
||||||
|
template <typename Property>
|
||||||
|
any_io_executor prefer(const Property& p,
|
||||||
|
typename constraint<
|
||||||
|
traits::prefer_member<const base_type&, const Property&>::is_valid
|
||||||
|
>::type = 0) const
|
||||||
|
{
|
||||||
|
return static_cast<const base_type&>(*this).prefer(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::require(
|
||||||
|
const execution::blocking_t::never_t&, int) const;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||||
|
const execution::blocking_t::possibly_t&, int) const;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||||
|
const execution::outstanding_work_t::tracked_t&, int) const;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||||
|
const execution::outstanding_work_t::untracked_t&, int) const;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||||
|
const execution::relationship_t::fork_t&, int) const;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ASIO_DECL any_io_executor any_io_executor::prefer(
|
||||||
|
const execution::relationship_t::continuation_t&, int) const;
|
||||||
|
|
||||||
|
namespace traits {
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct equality_comparable<any_io_executor>
|
||||||
|
{
|
||||||
|
static const bool is_valid = true;
|
||||||
|
static const bool is_noexcept = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct execute_member<any_io_executor, F>
|
||||||
|
{
|
||||||
|
static const bool is_valid = true;
|
||||||
|
static const bool is_noexcept = false;
|
||||||
|
typedef void result_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
template <typename Prop>
|
||||||
|
struct query_member<any_io_executor, Prop> :
|
||||||
|
query_member<any_io_executor::base_type, Prop>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
template <typename Prop>
|
||||||
|
struct require_member<any_io_executor, Prop> :
|
||||||
|
require_member<any_io_executor::base_type, Prop>
|
||||||
|
{
|
||||||
|
typedef any_io_executor result_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
template <typename Prop>
|
||||||
|
struct prefer_member<any_io_executor, Prop> :
|
||||||
|
prefer_member<any_io_executor::base_type, Prop>
|
||||||
|
{
|
||||||
|
typedef any_io_executor result_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
||||||
|
|
||||||
|
} // namespace traits
|
||||||
|
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HEADER_ONLY) \
|
||||||
|
&& !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
# include "asio/impl/any_io_executor.ipp"
|
||||||
|
#endif // defined(ASIO_HEADER_ONLY)
|
||||||
|
// && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
|
||||||
|
|
||||||
|
#endif // ASIO_ANY_IO_EXECUTOR_HPP
|
177
lib/asio/include/asio/associated_allocator.hpp
Normal file
177
lib/asio/include/asio/associated_allocator.hpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
//
|
||||||
|
// associated_allocator.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_ASSOCIATED_ALLOCATOR_HPP
|
||||||
|
#define ASIO_ASSOCIATED_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/detail/functional.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename T, typename Allocator>
|
||||||
|
struct associated_allocator;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct has_allocator_type : false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_allocator_type<T,
|
||||||
|
typename void_type<typename T::allocator_type>::type>
|
||||||
|
: true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E, typename = void, typename = void>
|
||||||
|
struct associated_allocator_impl
|
||||||
|
{
|
||||||
|
typedef E type;
|
||||||
|
|
||||||
|
static type get(const T&, const E& e) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E>
|
||||||
|
struct associated_allocator_impl<T, E,
|
||||||
|
typename void_type<typename T::allocator_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::allocator_type type;
|
||||||
|
|
||||||
|
static type get(const T& t, const E&) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return t.get_allocator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E>
|
||||||
|
struct associated_allocator_impl<T, E,
|
||||||
|
typename enable_if<
|
||||||
|
!has_allocator_type<T>::value
|
||||||
|
>::type,
|
||||||
|
typename void_type<
|
||||||
|
typename associator<associated_allocator, T, E>::type
|
||||||
|
>::type> : associator<associated_allocator, T, E>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Traits type used to obtain the allocator associated with an object.
|
||||||
|
/**
|
||||||
|
* A program may specialise this traits type if the @c T template parameter in
|
||||||
|
* the specialisation is a user-defined type. The template parameter @c
|
||||||
|
* Allocator shall be a type meeting the Allocator requirements.
|
||||||
|
*
|
||||||
|
* Specialisations shall meet the following requirements, where @c t is a const
|
||||||
|
* reference to an object of type @c T, and @c a is an object of type @c
|
||||||
|
* Allocator.
|
||||||
|
*
|
||||||
|
* @li Provide a nested typedef @c type that identifies a type meeting the
|
||||||
|
* Allocator requirements.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t) and with return type @c type.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t,a) and with return type @c type.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Allocator = std::allocator<void> >
|
||||||
|
struct associated_allocator
|
||||||
|
{
|
||||||
|
/// If @c T has a nested type @c allocator_type, <tt>T::allocator_type</tt>.
|
||||||
|
/// Otherwise @c Allocator.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef see_below type;
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef typename detail::associated_allocator_impl<T, Allocator>::type type;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// If @c T has a nested type @c allocator_type, returns
|
||||||
|
/// <tt>t.get_allocator()</tt>. Otherwise returns @c a.
|
||||||
|
static type get(const T& t,
|
||||||
|
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return detail::associated_allocator_impl<T, Allocator>::get(t, a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated allocator.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_allocator<T>::get(t)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
ASIO_NODISCARD inline typename associated_allocator<T>::type
|
||||||
|
get_associated_allocator(const T& t) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_allocator<T>::get(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated allocator.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T, typename Allocator>
|
||||||
|
ASIO_NODISCARD inline typename associated_allocator<T, Allocator>::type
|
||||||
|
get_associated_allocator(const T& t, const Allocator& a) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_allocator<T, Allocator>::get(t, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename T, typename Allocator = std::allocator<void> >
|
||||||
|
using associated_allocator_t
|
||||||
|
= typename associated_allocator<T, Allocator>::type;
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Specialisation of associated_allocator for @c std::reference_wrapper.
|
||||||
|
template <typename T, typename Allocator>
|
||||||
|
struct associated_allocator<reference_wrapper<T>, Allocator>
|
||||||
|
{
|
||||||
|
/// Forwards @c type to the associator specialisation for the unwrapped type
|
||||||
|
/// @c T.
|
||||||
|
typedef typename associated_allocator<T, Allocator>::type type;
|
||||||
|
|
||||||
|
/// Forwards the request to get the allocator to the associator specialisation
|
||||||
|
/// for the unwrapped type @c T.
|
||||||
|
static type get(reference_wrapper<T> t,
|
||||||
|
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_allocator<T, Allocator>::get(t.get(), a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_ASSOCIATED_ALLOCATOR_HPP
|
178
lib/asio/include/asio/associated_cancellation_slot.hpp
Normal file
178
lib/asio/include/asio/associated_cancellation_slot.hpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
//
|
||||||
|
// associated_cancellation_slot.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
|
||||||
|
#define ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/cancellation_signal.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename T, typename CancellationSlot>
|
||||||
|
struct associated_cancellation_slot;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct has_cancellation_slot_type : false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_cancellation_slot_type<T,
|
||||||
|
typename void_type<typename T::cancellation_slot_type>::type>
|
||||||
|
: true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename S, typename = void, typename = void>
|
||||||
|
struct associated_cancellation_slot_impl
|
||||||
|
{
|
||||||
|
typedef void asio_associated_cancellation_slot_is_unspecialised;
|
||||||
|
|
||||||
|
typedef S type;
|
||||||
|
|
||||||
|
static type get(const T&, const S& s = S()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
struct associated_cancellation_slot_impl<T, S,
|
||||||
|
typename void_type<typename T::cancellation_slot_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::cancellation_slot_type type;
|
||||||
|
|
||||||
|
static type get(const T& t, const S& = S()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return t.get_cancellation_slot();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
struct associated_cancellation_slot_impl<T, S,
|
||||||
|
typename enable_if<
|
||||||
|
!has_cancellation_slot_type<T>::value
|
||||||
|
>::type,
|
||||||
|
typename void_type<
|
||||||
|
typename associator<associated_cancellation_slot, T, S>::type
|
||||||
|
>::type> : associator<associated_cancellation_slot, T, S>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Traits type used to obtain the cancellation_slot associated with an object.
|
||||||
|
/**
|
||||||
|
* A program may specialise this traits type if the @c T template parameter in
|
||||||
|
* the specialisation is a user-defined type. The template parameter @c
|
||||||
|
* CancellationSlot shall be a type meeting the CancellationSlot requirements.
|
||||||
|
*
|
||||||
|
* Specialisations shall meet the following requirements, where @c t is a const
|
||||||
|
* reference to an object of type @c T, and @c s is an object of type @c
|
||||||
|
* CancellationSlot.
|
||||||
|
*
|
||||||
|
* @li Provide a nested typedef @c type that identifies a type meeting the
|
||||||
|
* CancellationSlot requirements.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t) and with return type @c type.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t,s) and with return type @c type.
|
||||||
|
*/
|
||||||
|
template <typename T, typename CancellationSlot = cancellation_slot>
|
||||||
|
struct associated_cancellation_slot
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: detail::associated_cancellation_slot_impl<T, CancellationSlot>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// If @c T has a nested type @c cancellation_slot_type,
|
||||||
|
/// <tt>T::cancellation_slot_type</tt>. Otherwise
|
||||||
|
/// @c CancellationSlot.
|
||||||
|
typedef see_below type;
|
||||||
|
|
||||||
|
/// If @c T has a nested type @c cancellation_slot_type, returns
|
||||||
|
/// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s.
|
||||||
|
static type get(const T& t,
|
||||||
|
const CancellationSlot& s = CancellationSlot()) ASIO_NOEXCEPT;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated cancellation_slot.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_cancellation_slot<T>::get(t)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
ASIO_NODISCARD inline typename associated_cancellation_slot<T>::type
|
||||||
|
get_associated_cancellation_slot(const T& t) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_cancellation_slot<T>::get(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated cancellation_slot.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_cancellation_slot<T,
|
||||||
|
* CancellationSlot>::get(t, st)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T, typename CancellationSlot>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
typename associated_cancellation_slot<T, CancellationSlot>::type
|
||||||
|
get_associated_cancellation_slot(const T& t,
|
||||||
|
const CancellationSlot& st) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_cancellation_slot<T, CancellationSlot>::get(t, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename T, typename CancellationSlot = cancellation_slot>
|
||||||
|
using associated_cancellation_slot_t =
|
||||||
|
typename associated_cancellation_slot<T, CancellationSlot>::type;
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename S, typename = void>
|
||||||
|
struct associated_cancellation_slot_forwarding_base
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
struct associated_cancellation_slot_forwarding_base<T, S,
|
||||||
|
typename enable_if<
|
||||||
|
is_same<
|
||||||
|
typename associated_cancellation_slot<T,
|
||||||
|
S>::asio_associated_cancellation_slot_is_unspecialised,
|
||||||
|
void
|
||||||
|
>::value
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef void asio_associated_cancellation_slot_is_unspecialised;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
|
222
lib/asio/include/asio/associated_executor.hpp
Normal file
222
lib/asio/include/asio/associated_executor.hpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
//
|
||||||
|
// associated_executor.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_ASSOCIATED_EXECUTOR_HPP
|
||||||
|
#define ASIO_ASSOCIATED_EXECUTOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/detail/functional.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
#include "asio/system_executor.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
struct associated_executor;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct has_executor_type : false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_executor_type<T,
|
||||||
|
typename void_type<typename T::executor_type>::type>
|
||||||
|
: true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E, typename = void, typename = void>
|
||||||
|
struct associated_executor_impl
|
||||||
|
{
|
||||||
|
typedef void asio_associated_executor_is_unspecialised;
|
||||||
|
|
||||||
|
typedef E type;
|
||||||
|
|
||||||
|
static type get(const T&, const E& e = E()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E>
|
||||||
|
struct associated_executor_impl<T, E,
|
||||||
|
typename void_type<typename T::executor_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::executor_type type;
|
||||||
|
|
||||||
|
static type get(const T& t, const E& = E()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return t.get_executor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E>
|
||||||
|
struct associated_executor_impl<T, E,
|
||||||
|
typename enable_if<
|
||||||
|
!has_executor_type<T>::value
|
||||||
|
>::type,
|
||||||
|
typename void_type<
|
||||||
|
typename associator<associated_executor, T, E>::type
|
||||||
|
>::type> : associator<associated_executor, T, E>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Traits type used to obtain the executor associated with an object.
|
||||||
|
/**
|
||||||
|
* A program may specialise this traits type if the @c T template parameter in
|
||||||
|
* the specialisation is a user-defined type. The template parameter @c
|
||||||
|
* Executor shall be a type meeting the Executor requirements.
|
||||||
|
*
|
||||||
|
* Specialisations shall meet the following requirements, where @c t is a const
|
||||||
|
* reference to an object of type @c T, and @c e is an object of type @c
|
||||||
|
* Executor.
|
||||||
|
*
|
||||||
|
* @li Provide a nested typedef @c type that identifies a type meeting the
|
||||||
|
* Executor requirements.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t) and with return type @c type.
|
||||||
|
*
|
||||||
|
* @li Provide a noexcept static member function named @c get, callable as @c
|
||||||
|
* get(t,e) and with return type @c type.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Executor = system_executor>
|
||||||
|
struct associated_executor
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: detail::associated_executor_impl<T, Executor>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
|
||||||
|
/// Otherwise @c Executor.
|
||||||
|
typedef see_below type;
|
||||||
|
|
||||||
|
/// If @c T has a nested type @c executor_type, returns
|
||||||
|
/// <tt>t.get_executor()</tt>. Otherwise returns @c ex.
|
||||||
|
static type get(const T& t,
|
||||||
|
const Executor& ex = Executor()) ASIO_NOEXCEPT;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated executor.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_executor<T>::get(t)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
ASIO_NODISCARD inline typename associated_executor<T>::type
|
||||||
|
get_associated_executor(const T& t) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_executor<T>::get(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated executor.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>
|
||||||
|
*/
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
ASIO_NODISCARD inline typename associated_executor<T, Executor>::type
|
||||||
|
get_associated_executor(const T& t, const Executor& ex,
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_executor<T, Executor>::get(t, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to obtain an object's associated executor.
|
||||||
|
/**
|
||||||
|
* @returns <tt>associated_executor<T, typename
|
||||||
|
* ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
|
||||||
|
*/
|
||||||
|
template <typename T, typename ExecutionContext>
|
||||||
|
ASIO_NODISCARD inline typename associated_executor<T,
|
||||||
|
typename ExecutionContext::executor_type>::type
|
||||||
|
get_associated_executor(const T& t, ExecutionContext& ctx,
|
||||||
|
typename constraint<is_convertible<ExecutionContext&,
|
||||||
|
execution_context&>::value>::type = 0) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_executor<T,
|
||||||
|
typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename T, typename Executor = system_executor>
|
||||||
|
using associated_executor_t = typename associated_executor<T, Executor>::type;
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename E, typename = void>
|
||||||
|
struct associated_executor_forwarding_base
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename E>
|
||||||
|
struct associated_executor_forwarding_base<T, E,
|
||||||
|
typename enable_if<
|
||||||
|
is_same<
|
||||||
|
typename associated_executor<T,
|
||||||
|
E>::asio_associated_executor_is_unspecialised,
|
||||||
|
void
|
||||||
|
>::value
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef void asio_associated_executor_is_unspecialised;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Specialisation of associated_executor for @c std::reference_wrapper.
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
struct associated_executor<reference_wrapper<T>, Executor>
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: detail::associated_executor_forwarding_base<T, Executor>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
/// Forwards @c type to the associator specialisation for the unwrapped type
|
||||||
|
/// @c T.
|
||||||
|
typedef typename associated_executor<T, Executor>::type type;
|
||||||
|
|
||||||
|
/// Forwards the request to get the executor to the associator specialisation
|
||||||
|
/// for the unwrapped type @c T.
|
||||||
|
static type get(reference_wrapper<T> t,
|
||||||
|
const Executor& ex = Executor()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return associated_executor<T, Executor>::get(t.get(), ex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_ASSOCIATED_EXECUTOR_HPP
|
35
lib/asio/include/asio/associator.hpp
Normal file
35
lib/asio/include/asio/associator.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// associator.hpp
|
||||||
|
// ~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_ASSOCIATOR_HPP
|
||||||
|
#define ASIO_ASSOCIATOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Used to generically specialise associators for a type.
|
||||||
|
template <template <typename, typename> class Associator,
|
||||||
|
typename T, typename DefaultCandidate>
|
||||||
|
struct associator
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_ASSOCIATOR_HPP
|
1271
lib/asio/include/asio/async_result.hpp
Normal file
1271
lib/asio/include/asio/async_result.hpp
Normal file
File diff suppressed because it is too large
Load Diff
142
lib/asio/include/asio/awaitable.hpp
Normal file
142
lib/asio/include/asio/awaitable.hpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
//
|
||||||
|
// awaitable.hpp
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_AWAITABLE_HPP
|
||||||
|
#define ASIO_AWAITABLE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
# include <coroutine>
|
||||||
|
#else // defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
# include <experimental/coroutine>
|
||||||
|
#endif // defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
using std::coroutine_handle;
|
||||||
|
using std::suspend_always;
|
||||||
|
#else // defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
using std::experimental::coroutine_handle;
|
||||||
|
using std::experimental::suspend_always;
|
||||||
|
#endif // defined(ASIO_HAS_STD_COROUTINE)
|
||||||
|
|
||||||
|
template <typename> class awaitable_thread;
|
||||||
|
template <typename, typename> class awaitable_frame;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// The return type of a coroutine or asynchronous operation.
|
||||||
|
template <typename T, typename Executor = any_io_executor>
|
||||||
|
class ASIO_NODISCARD awaitable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the awaited value.
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
/// The executor type that will be used for the coroutine.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Default constructor.
|
||||||
|
constexpr awaitable() noexcept
|
||||||
|
: frame_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move constructor.
|
||||||
|
awaitable(awaitable&& other) noexcept
|
||||||
|
: frame_(std::exchange(other.frame_, nullptr))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
~awaitable()
|
||||||
|
{
|
||||||
|
if (frame_)
|
||||||
|
frame_->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move assignment.
|
||||||
|
awaitable& operator=(awaitable&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
frame_ = std::exchange(other.frame_, nullptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the awaitable refers to a future result.
|
||||||
|
bool valid() const noexcept
|
||||||
|
{
|
||||||
|
return !!frame_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
// Support for co_await keyword.
|
||||||
|
bool await_ready() const noexcept
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for co_await keyword.
|
||||||
|
template <class U>
|
||||||
|
void await_suspend(
|
||||||
|
detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h)
|
||||||
|
{
|
||||||
|
frame_->push_frame(&h.promise());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for co_await keyword.
|
||||||
|
T await_resume()
|
||||||
|
{
|
||||||
|
return awaitable(static_cast<awaitable&&>(*this)).frame_->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename> friend class detail::awaitable_thread;
|
||||||
|
template <typename, typename> friend class detail::awaitable_frame;
|
||||||
|
|
||||||
|
// Not copy constructible or copy assignable.
|
||||||
|
awaitable(const awaitable&) = delete;
|
||||||
|
awaitable& operator=(const awaitable&) = delete;
|
||||||
|
|
||||||
|
// Construct the awaitable from a coroutine's frame object.
|
||||||
|
explicit awaitable(detail::awaitable_frame<T, Executor>* a)
|
||||||
|
: frame_(a)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::awaitable_frame<T, Executor>* frame_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/awaitable.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_AWAITABLE_HPP
|
1351
lib/asio/include/asio/basic_datagram_socket.hpp
Normal file
1351
lib/asio/include/asio/basic_datagram_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
709
lib/asio/include/asio/basic_deadline_timer.hpp
Normal file
709
lib/asio/include/asio/basic_deadline_timer.hpp
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
//
|
||||||
|
// basic_deadline_timer.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_DEADLINE_TIMER_HPP
|
||||||
|
#define ASIO_BASIC_DEADLINE_TIMER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/detail/deadline_timer_service.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/time_traits.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Provides waitable timer functionality.
|
||||||
|
/**
|
||||||
|
* The basic_deadline_timer class template provides the ability to perform a
|
||||||
|
* blocking or asynchronous wait for a timer to expire.
|
||||||
|
*
|
||||||
|
* A deadline timer is always in one of two states: "expired" or "not expired".
|
||||||
|
* If the wait() or async_wait() function is called on an expired timer, the
|
||||||
|
* wait operation will complete immediately.
|
||||||
|
*
|
||||||
|
* Most applications will use the asio::deadline_timer typedef.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Examples
|
||||||
|
* Performing a blocking wait:
|
||||||
|
* @code
|
||||||
|
* // Construct a timer without setting an expiry time.
|
||||||
|
* asio::deadline_timer timer(my_context);
|
||||||
|
*
|
||||||
|
* // Set an expiry time relative to now.
|
||||||
|
* timer.expires_from_now(boost::posix_time::seconds(5));
|
||||||
|
*
|
||||||
|
* // Wait for the timer to expire.
|
||||||
|
* timer.wait();
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* Performing an asynchronous wait:
|
||||||
|
* @code
|
||||||
|
* void handler(const asio::error_code& error)
|
||||||
|
* {
|
||||||
|
* if (!error)
|
||||||
|
* {
|
||||||
|
* // Timer expired.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* // Construct a timer with an absolute expiry time.
|
||||||
|
* asio::deadline_timer timer(my_context,
|
||||||
|
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
|
||||||
|
*
|
||||||
|
* // Start an asynchronous wait.
|
||||||
|
* timer.async_wait(handler);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Changing an active deadline_timer's expiry time
|
||||||
|
*
|
||||||
|
* Changing the expiry time of a timer while there are pending asynchronous
|
||||||
|
* waits causes those wait operations to be cancelled. To ensure that the action
|
||||||
|
* associated with the timer is performed only once, use something like this:
|
||||||
|
* used:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* void on_some_event()
|
||||||
|
* {
|
||||||
|
* if (my_timer.expires_from_now(seconds(5)) > 0)
|
||||||
|
* {
|
||||||
|
* // We managed to cancel the timer. Start new asynchronous wait.
|
||||||
|
* my_timer.async_wait(on_timeout);
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Too late, timer has already expired!
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void on_timeout(const asio::error_code& e)
|
||||||
|
* {
|
||||||
|
* if (e != asio::error::operation_aborted)
|
||||||
|
* {
|
||||||
|
* // Timer was not cancelled, take necessary action.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @li The asio::basic_deadline_timer::expires_from_now() function
|
||||||
|
* cancels any pending asynchronous waits, and returns the number of
|
||||||
|
* asynchronous waits that were cancelled. If it returns 0 then you were too
|
||||||
|
* late and the wait handler has already been executed, or will soon be
|
||||||
|
* executed. If it returns 1 then the wait handler was successfully cancelled.
|
||||||
|
*
|
||||||
|
* @li If a wait handler is cancelled, the asio::error_code passed to
|
||||||
|
* it contains the value asio::error::operation_aborted.
|
||||||
|
*/
|
||||||
|
template <typename Time,
|
||||||
|
typename TimeTraits = asio::time_traits<Time>,
|
||||||
|
typename Executor = any_io_executor>
|
||||||
|
class basic_deadline_timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the timer type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The timer type when rebound to the specified executor.
|
||||||
|
typedef basic_deadline_timer<Time, TimeTraits, Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The time traits type.
|
||||||
|
typedef TimeTraits traits_type;
|
||||||
|
|
||||||
|
/// The time type.
|
||||||
|
typedef typename traits_type::time_type time_type;
|
||||||
|
|
||||||
|
/// The duration type.
|
||||||
|
typedef typename traits_type::duration_type duration_type;
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer without setting an expiry time. The
|
||||||
|
* expires_at() or expires_from_now() functions must be called to set an
|
||||||
|
* expiry time before the timer can be waited on.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*/
|
||||||
|
explicit basic_deadline_timer(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer without setting an expiry time. The
|
||||||
|
* expires_at() or expires_from_now() functions must be called to set an
|
||||||
|
* expiry time before the timer can be waited on.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_deadline_timer(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||||
|
* as an absolute time.
|
||||||
|
*/
|
||||||
|
basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||||
|
* as an absolute time.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
basic_deadline_timer(const executor_type& ex,
|
||||||
|
const duration_type& expiry_time)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_from_now");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_deadline_timer(ExecutionContext& context,
|
||||||
|
const duration_type& expiry_time,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_from_now");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_deadline_timer from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a timer from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_deadline_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_deadline_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_deadline_timer(basic_deadline_timer&& other)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_deadline_timer from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a timer from one object to another. Cancels
|
||||||
|
* any outstanding asynchronous operations associated with the target object.
|
||||||
|
*
|
||||||
|
* @param other The other basic_deadline_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_deadline_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_deadline_timer& operator=(basic_deadline_timer&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the timer.
|
||||||
|
/**
|
||||||
|
* This function destroys the timer, cancelling any outstanding asynchronous
|
||||||
|
* wait operations associated with the timer as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_deadline_timer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel any asynchronous operations that are waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the timer. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel any asynchronous operations that are waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the timer. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancels one asynchronous operation that is waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of one pending asynchronous wait
|
||||||
|
* operation against the timer. Handlers are cancelled in FIFO order. The
|
||||||
|
* handler for the cancelled operation will be invoked with the
|
||||||
|
* asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled. That is,
|
||||||
|
* either 0 or 1.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel_one() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel_one()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().cancel_one(
|
||||||
|
impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel_one");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancels one asynchronous operation that is waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of one pending asynchronous wait
|
||||||
|
* operation against the timer. Handlers are cancelled in FIFO order. The
|
||||||
|
* handler for the cancelled operation will be invoked with the
|
||||||
|
* asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled. That is,
|
||||||
|
* either 0 or 1.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel_one() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel_one(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the timer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the timer's current expiry time.
|
||||||
|
* Whether the timer has expired or not does not affect this value.
|
||||||
|
*/
|
||||||
|
time_type expires_at() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_at(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the timer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_at() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_at(const time_type& expiry_time)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().expires_at(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the timer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_at() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_at(const time_type& expiry_time,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_at(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the timer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the timer's current expiry time.
|
||||||
|
* Whether the timer has expired or not does not affect this value.
|
||||||
|
*/
|
||||||
|
duration_type expires_from_now() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_from_now(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the timer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_from_now() is called,
|
||||||
|
* then the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_from_now(const duration_type& expiry_time)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_from_now");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the timer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_from_now() is called,
|
||||||
|
* then the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_from_now(const duration_type& expiry_time,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a blocking wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function is used to wait for the timer to expire. This function
|
||||||
|
* blocks and does not return until the timer has expired.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().wait(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a blocking wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function is used to wait for the timer to expire. This function
|
||||||
|
* blocks and does not return until the timer has expired.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
void wait(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().wait(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function may be used to initiate an asynchronous wait against the
|
||||||
|
* timer. It is an initiating function for an @ref asynchronous_operation,
|
||||||
|
* and always returns immediately.
|
||||||
|
*
|
||||||
|
* For each call to async_wait(), the completion handler will be called
|
||||||
|
* exactly once. The completion handler will be called when:
|
||||||
|
*
|
||||||
|
* @li The timer has expired.
|
||||||
|
*
|
||||||
|
* @li The timer was cancelled, in which case the handler is passed the error
|
||||||
|
* code asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the timer expires. Potential
|
||||||
|
* completion tokens include @ref use_future, @ref use_awaitable, @ref
|
||||||
|
* yield_context, or a function object with the correct completion signature.
|
||||||
|
* The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error // Result of operation.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code) @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* This asynchronous operation supports cancellation for the following
|
||||||
|
* asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))
|
||||||
|
WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WaitToken,
|
||||||
|
void (asio::error_code))
|
||||||
|
async_wait(
|
||||||
|
ASIO_MOVE_ARG(WaitToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WaitToken, void (asio::error_code)>(
|
||||||
|
initiate_async_wait(this), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_deadline_timer(const basic_deadline_timer&) ASIO_DELETED;
|
||||||
|
basic_deadline_timer& operator=(
|
||||||
|
const basic_deadline_timer&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_wait
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_wait(basic_deadline_timer* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WaitHandler>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WaitHandler) handler) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WaitHandler.
|
||||||
|
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_wait(
|
||||||
|
self_->impl_.get_implementation(),
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_deadline_timer* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
detail::io_object_impl<
|
||||||
|
detail::deadline_timer_service<TimeTraits>, Executor> impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_DEADLINE_TIMER_HPP
|
829
lib/asio/include/asio/basic_file.hpp
Normal file
829
lib/asio/include/asio/basic_file.hpp
Normal file
@ -0,0 +1,829 @@
|
|||||||
|
//
|
||||||
|
// basic_file.hpp
|
||||||
|
// ~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_FILE_HPP
|
||||||
|
#define ASIO_BASIC_FILE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_FILE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/cstdint.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/post.hpp"
|
||||||
|
#include "asio/file_base.hpp"
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
# include "asio/detail/win_iocp_file_service.hpp"
|
||||||
|
#elif defined(ASIO_HAS_IO_URING)
|
||||||
|
# include "asio/detail/io_uring_file_service.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_FILE_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_FILE_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_file;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_FILE_FWD_DECL)
|
||||||
|
|
||||||
|
/// Provides file functionality.
|
||||||
|
/**
|
||||||
|
* The basic_file class template provides functionality that is common to both
|
||||||
|
* stream-oriented and random-access files.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*/
|
||||||
|
template <typename Executor>
|
||||||
|
class basic_file
|
||||||
|
: public file_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the file type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The file type when rebound to the specified executor.
|
||||||
|
typedef basic_file<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a file.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IOCP)
|
||||||
|
typedef detail::win_iocp_file_service::native_handle_type native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING)
|
||||||
|
typedef detail::io_uring_file_service::native_handle_type native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*/
|
||||||
|
explicit basic_file(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_file(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file and opens it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*/
|
||||||
|
explicit basic_file(const executor_type& ex,
|
||||||
|
const char* path, file_base::flags open_flags)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file and opens it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_file(ExecutionContext& context,
|
||||||
|
const char* path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file and opens it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*/
|
||||||
|
explicit basic_file(const executor_type& ex,
|
||||||
|
const std::string& path, file_base::flags open_flags)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file and opens it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_file(ExecutionContext& context,
|
||||||
|
const std::string& path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_file on an existing native file handle.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file object to hold an existing native file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file A native file handle.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_file(const executor_type& ex, const native_handle_type& native_file)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(
|
||||||
|
impl_.get_implementation(), native_file, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_file on an existing native file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file object to hold an existing native file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file A native file.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_file(ExecutionContext& context, const native_handle_type& native_file,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(
|
||||||
|
impl_.get_implementation(), native_file, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_file from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_file object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_file(const executor_type&) constructor.
|
||||||
|
*/
|
||||||
|
basic_file(basic_file&& other) ASIO_NOEXCEPT
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_file from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_file object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_file(const executor_type&) constructor.
|
||||||
|
*/
|
||||||
|
basic_file& operator=(basic_file&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All files have access to each other's implementations.
|
||||||
|
template <typename Executor1>
|
||||||
|
friend class basic_file;
|
||||||
|
|
||||||
|
/// Move-construct a basic_file from a file of another executor type.
|
||||||
|
/**
|
||||||
|
* This constructor moves a file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_file object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_file(const executor_type&) constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
basic_file(basic_file<Executor1>&& other,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_file from a file of another executor type.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_file object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_file(const executor_type&) constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
basic_file&
|
||||||
|
>::type operator=(basic_file<Executor1> && other)
|
||||||
|
{
|
||||||
|
basic_file tmp(std::move(other));
|
||||||
|
impl_ = std::move(tmp.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the file using the specified path.
|
||||||
|
/**
|
||||||
|
* This function opens the file so that it will use the specified path.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::stream_file file(my_context);
|
||||||
|
* file.open("/path/to/my/file", asio::stream_file::read_only);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
void open(const char* path, file_base::flags open_flags)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the file using the specified path.
|
||||||
|
/**
|
||||||
|
* This function opens the file so that it will use the specified path.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::stream_file file(my_context);
|
||||||
|
* asio::error_code ec;
|
||||||
|
* file.open("/path/to/my/file", asio::stream_file::read_only, ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID open(const char* path,
|
||||||
|
file_base::flags open_flags, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the file using the specified path.
|
||||||
|
/**
|
||||||
|
* This function opens the file so that it will use the specified path.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::stream_file file(my_context);
|
||||||
|
* file.open("/path/to/my/file", asio::stream_file::read_only);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
void open(const std::string& path, file_base::flags open_flags)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the file using the specified path.
|
||||||
|
/**
|
||||||
|
* This function opens the file so that it will use the specified path.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::stream_file file(my_context);
|
||||||
|
* asio::error_code ec;
|
||||||
|
* file.open("/path/to/my/file", asio::stream_file::read_only, ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID open(const std::string& path,
|
||||||
|
file_base::flags open_flags, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().open(impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native file to the file.
|
||||||
|
/*
|
||||||
|
* This function opens the file to hold an existing native file.
|
||||||
|
*
|
||||||
|
* @param native_file A native file.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void assign(const native_handle_type& native_file)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(
|
||||||
|
impl_.get_implementation(), native_file, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native file to the file.
|
||||||
|
/*
|
||||||
|
* This function opens the file to hold an existing native file.
|
||||||
|
*
|
||||||
|
* @param native_file A native file.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_file,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().assign(
|
||||||
|
impl_.get_implementation(), native_file, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine whether the file is open.
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().is_open(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the file.
|
||||||
|
/**
|
||||||
|
* This function is used to close the file. Any asynchronous read or write
|
||||||
|
* operations will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. Note that, even if
|
||||||
|
* the function indicates an error, the underlying descriptor is closed.
|
||||||
|
*/
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the file.
|
||||||
|
/**
|
||||||
|
* This function is used to close the file. Any asynchronous read or write
|
||||||
|
* operations will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any. Note that, even if
|
||||||
|
* the function indicates an error, the underlying descriptor is closed.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::stream_file file(my_context);
|
||||||
|
* ...
|
||||||
|
* asio::error_code ec;
|
||||||
|
* file.close(ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Release ownership of the underlying native file.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read and write
|
||||||
|
* operations to finish immediately, and the handlers for cancelled
|
||||||
|
* operations will be passed the asio::error::operation_aborted error.
|
||||||
|
* Ownership of the native file is then transferred to the caller.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note This function is unsupported on Windows versions prior to Windows
|
||||||
|
* 8.1, and will fail with asio::error::operation_not_supported on
|
||||||
|
* these platforms.
|
||||||
|
*/
|
||||||
|
#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
|
||||||
|
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
|
||||||
|
__declspec(deprecated("This function always fails with "
|
||||||
|
"operation_not_supported when used on Windows versions "
|
||||||
|
"prior to Windows 8.1."))
|
||||||
|
#endif
|
||||||
|
native_handle_type release()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
native_handle_type s = impl_.get_service().release(
|
||||||
|
impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "release");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Release ownership of the underlying native file.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read and write
|
||||||
|
* operations to finish immediately, and the handlers for cancelled
|
||||||
|
* operations will be passed the asio::error::operation_aborted error.
|
||||||
|
* Ownership of the native file is then transferred to the caller.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @note This function is unsupported on Windows versions prior to Windows
|
||||||
|
* 8.1, and will fail with asio::error::operation_not_supported on
|
||||||
|
* these platforms.
|
||||||
|
*/
|
||||||
|
#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
|
||||||
|
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
|
||||||
|
__declspec(deprecated("This function always fails with "
|
||||||
|
"operation_not_supported when used on Windows versions "
|
||||||
|
"prior to Windows 8.1."))
|
||||||
|
#endif
|
||||||
|
native_handle_type release(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().release(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the native file representation.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the underlying representation of the
|
||||||
|
* file. This is intended to allow access to native file functionality
|
||||||
|
* that is not otherwise provided.
|
||||||
|
*/
|
||||||
|
native_handle_type native_handle()
|
||||||
|
{
|
||||||
|
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the file.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read and write
|
||||||
|
* operations to finish immediately, and the handlers for cancelled
|
||||||
|
* operations will be passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note Calls to cancel() will always fail with
|
||||||
|
* asio::error::operation_not_supported when run on Windows XP, Windows
|
||||||
|
* Server 2003, and earlier versions of Windows, unless
|
||||||
|
* ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
|
||||||
|
* two issues that should be considered before enabling its use:
|
||||||
|
*
|
||||||
|
* @li It will only cancel asynchronous operations that were initiated in the
|
||||||
|
* current thread.
|
||||||
|
*
|
||||||
|
* @li It can appear to complete without error, but the request to cancel the
|
||||||
|
* unfinished operations may be silently ignored by the operating system.
|
||||||
|
* Whether it works or not seems to depend on the drivers that are installed.
|
||||||
|
*
|
||||||
|
* For portable cancellation, consider using the close() function to
|
||||||
|
* simultaneously cancel the outstanding operations and close the file.
|
||||||
|
*
|
||||||
|
* When running on Windows Vista, Windows Server 2008, and later, the
|
||||||
|
* CancelIoEx function is always used. This function does not have the
|
||||||
|
* problems described above.
|
||||||
|
*/
|
||||||
|
#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
|
||||||
|
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
|
||||||
|
&& !defined(ASIO_ENABLE_CANCELIO)
|
||||||
|
__declspec(deprecated("By default, this function always fails with "
|
||||||
|
"operation_not_supported when used on Windows XP, Windows Server 2003, "
|
||||||
|
"or earlier. Consult documentation for details."))
|
||||||
|
#endif
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the file.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read and write
|
||||||
|
* operations to finish immediately, and the handlers for cancelled
|
||||||
|
* operations will be passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @note Calls to cancel() will always fail with
|
||||||
|
* asio::error::operation_not_supported when run on Windows XP, Windows
|
||||||
|
* Server 2003, and earlier versions of Windows, unless
|
||||||
|
* ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
|
||||||
|
* two issues that should be considered before enabling its use:
|
||||||
|
*
|
||||||
|
* @li It will only cancel asynchronous operations that were initiated in the
|
||||||
|
* current thread.
|
||||||
|
*
|
||||||
|
* @li It can appear to complete without error, but the request to cancel the
|
||||||
|
* unfinished operations may be silently ignored by the operating system.
|
||||||
|
* Whether it works or not seems to depend on the drivers that are installed.
|
||||||
|
*
|
||||||
|
* For portable cancellation, consider using the close() function to
|
||||||
|
* simultaneously cancel the outstanding operations and close the file.
|
||||||
|
*
|
||||||
|
* When running on Windows Vista, Windows Server 2008, and later, the
|
||||||
|
* CancelIoEx function is always used. This function does not have the
|
||||||
|
* problems described above.
|
||||||
|
*/
|
||||||
|
#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
|
||||||
|
&& (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
|
||||||
|
&& !defined(ASIO_ENABLE_CANCELIO)
|
||||||
|
__declspec(deprecated("By default, this function always fails with "
|
||||||
|
"operation_not_supported when used on Windows XP, Windows Server 2003, "
|
||||||
|
"or earlier. Consult documentation for details."))
|
||||||
|
#endif
|
||||||
|
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the size of the file.
|
||||||
|
/**
|
||||||
|
* This function determines the size of the file, in bytes.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
uint64_t size() const
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
uint64_t s = impl_.get_service().size(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "size");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the size of the file.
|
||||||
|
/**
|
||||||
|
* This function determines the size of the file, in bytes.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
uint64_t size(asio::error_code& ec) const
|
||||||
|
{
|
||||||
|
return impl_.get_service().size(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Alter the size of the file.
|
||||||
|
/**
|
||||||
|
* This function resizes the file to the specified size, in bytes. If the
|
||||||
|
* current file size exceeds @c n then any extra data is discarded. If the
|
||||||
|
* current size is less than @c n then the file is extended and filled with
|
||||||
|
* zeroes.
|
||||||
|
*
|
||||||
|
* @param n The new size for the file.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void resize(uint64_t n)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().resize(impl_.get_implementation(), n, ec);
|
||||||
|
asio::detail::throw_error(ec, "resize");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Alter the size of the file.
|
||||||
|
/**
|
||||||
|
* This function resizes the file to the specified size, in bytes. If the
|
||||||
|
* current file size exceeds @c n then any extra data is discarded. If the
|
||||||
|
* current size is less than @c n then the file is extended and filled with
|
||||||
|
* zeroes.
|
||||||
|
*
|
||||||
|
* @param n The new size for the file.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID resize(uint64_t n, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().resize(impl_.get_implementation(), n, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Synchronise the file to disk.
|
||||||
|
/**
|
||||||
|
* This function synchronises the file data and metadata to disk. Note that
|
||||||
|
* the semantics of this synchronisation vary between operation systems.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void sync_all()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().sync_all(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "sync_all");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Synchronise the file to disk.
|
||||||
|
/**
|
||||||
|
* This function synchronises the file data and metadata to disk. Note that
|
||||||
|
* the semantics of this synchronisation vary between operation systems.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID sync_all(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().sync_all(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Synchronise the file data to disk.
|
||||||
|
/**
|
||||||
|
* This function synchronises the file data to disk. Note that the semantics
|
||||||
|
* of this synchronisation vary between operation systems.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void sync_data()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().sync_data(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "sync_data");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Synchronise the file data to disk.
|
||||||
|
/**
|
||||||
|
* This function synchronises the file data to disk. Note that the semantics
|
||||||
|
* of this synchronisation vary between operation systems.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID sync_data(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().sync_data(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Protected destructor to prevent deletion through this type.
|
||||||
|
/**
|
||||||
|
* This function destroys the file, cancelling any outstanding asynchronous
|
||||||
|
* operations associated with the file as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
detail::io_object_impl<detail::win_iocp_file_service, Executor> impl_;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING)
|
||||||
|
detail::io_object_impl<detail::io_uring_file_service, Executor> impl_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_file(const basic_file&) ASIO_DELETED;
|
||||||
|
basic_file& operator=(const basic_file&) ASIO_DELETED;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_FILE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_FILE_HPP
|
290
lib/asio/include/asio/basic_io_object.hpp
Normal file
290
lib/asio/include/asio/basic_io_object.hpp
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
//
|
||||||
|
// basic_io_object.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_IO_OBJECT_HPP
|
||||||
|
#define ASIO_BASIC_IO_OBJECT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/io_context.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Type trait used to determine whether a service supports move.
|
||||||
|
template <typename IoObjectService>
|
||||||
|
class service_has_move
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef IoObjectService service_type;
|
||||||
|
typedef typename service_type::implementation_type implementation_type;
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
static auto asio_service_has_move_eval(T* t, U* u)
|
||||||
|
-> decltype(t->move_construct(*u, *u), char());
|
||||||
|
static char (&asio_service_has_move_eval(...))[2];
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool value =
|
||||||
|
sizeof(asio_service_has_move_eval(
|
||||||
|
static_cast<service_type*>(0),
|
||||||
|
static_cast<implementation_type*>(0))) == 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
/// Base class for all I/O objects.
|
||||||
|
/**
|
||||||
|
* @note All I/O objects are non-copyable. However, when using C++0x, certain
|
||||||
|
* I/O objects do support move construction and move assignment.
|
||||||
|
*/
|
||||||
|
#if !defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename IoObjectService>
|
||||||
|
#else
|
||||||
|
template <typename IoObjectService,
|
||||||
|
bool Movable = detail::service_has_move<IoObjectService>::value>
|
||||||
|
#endif
|
||||||
|
class basic_io_object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the service that will be used to provide I/O operations.
|
||||||
|
typedef IoObjectService service_type;
|
||||||
|
|
||||||
|
/// The underlying implementation type of I/O object.
|
||||||
|
typedef typename service_type::implementation_type implementation_type;
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use get_executor().) Get the io_context associated with the
|
||||||
|
/// object.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the io_context object that the I/O
|
||||||
|
* object uses to dispatch handlers for asynchronous operations.
|
||||||
|
*
|
||||||
|
* @return A reference to the io_context object that the I/O object will use
|
||||||
|
* to dispatch handlers. Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
asio::io_context& get_io_context()
|
||||||
|
{
|
||||||
|
return service_.get_io_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use get_executor().) Get the io_context associated with the
|
||||||
|
/// object.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the io_context object that the I/O
|
||||||
|
* object uses to dispatch handlers for asynchronous operations.
|
||||||
|
*
|
||||||
|
* @return A reference to the io_context object that the I/O object will use
|
||||||
|
* to dispatch handlers. Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
asio::io_context& get_io_service()
|
||||||
|
{
|
||||||
|
return service_.get_io_context();
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef asio::io_context::executor_type executor_type;
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return service_.get_io_context().get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Construct a basic_io_object.
|
||||||
|
/**
|
||||||
|
* Performs:
|
||||||
|
* @code get_service().construct(get_implementation()); @endcode
|
||||||
|
*/
|
||||||
|
explicit basic_io_object(asio::io_context& io_context)
|
||||||
|
: service_(asio::use_service<IoObjectService>(io_context))
|
||||||
|
{
|
||||||
|
service_.construct(implementation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_io_object.
|
||||||
|
/**
|
||||||
|
* Performs:
|
||||||
|
* @code get_service().move_construct(
|
||||||
|
* get_implementation(), other.get_implementation()); @endcode
|
||||||
|
*
|
||||||
|
* @note Available only for services that support movability,
|
||||||
|
*/
|
||||||
|
basic_io_object(basic_io_object&& other);
|
||||||
|
|
||||||
|
/// Move-assign a basic_io_object.
|
||||||
|
/**
|
||||||
|
* Performs:
|
||||||
|
* @code get_service().move_assign(get_implementation(),
|
||||||
|
* other.get_service(), other.get_implementation()); @endcode
|
||||||
|
*
|
||||||
|
* @note Available only for services that support movability,
|
||||||
|
*/
|
||||||
|
basic_io_object& operator=(basic_io_object&& other);
|
||||||
|
|
||||||
|
/// Perform a converting move-construction of a basic_io_object.
|
||||||
|
template <typename IoObjectService1>
|
||||||
|
basic_io_object(IoObjectService1& other_service,
|
||||||
|
typename IoObjectService1::implementation_type& other_implementation);
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Protected destructor to prevent deletion through this type.
|
||||||
|
/**
|
||||||
|
* Performs:
|
||||||
|
* @code get_service().destroy(get_implementation()); @endcode
|
||||||
|
*/
|
||||||
|
~basic_io_object()
|
||||||
|
{
|
||||||
|
service_.destroy(implementation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the service associated with the I/O object.
|
||||||
|
service_type& get_service()
|
||||||
|
{
|
||||||
|
return service_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the service associated with the I/O object.
|
||||||
|
const service_type& get_service() const
|
||||||
|
{
|
||||||
|
return service_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the underlying implementation of the I/O object.
|
||||||
|
implementation_type& get_implementation()
|
||||||
|
{
|
||||||
|
return implementation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the underlying implementation of the I/O object.
|
||||||
|
const implementation_type& get_implementation() const
|
||||||
|
{
|
||||||
|
return implementation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_io_object(const basic_io_object&);
|
||||||
|
basic_io_object& operator=(const basic_io_object&);
|
||||||
|
|
||||||
|
// The service associated with the I/O object.
|
||||||
|
service_type& service_;
|
||||||
|
|
||||||
|
/// The underlying implementation of the I/O object.
|
||||||
|
implementation_type implementation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
// Specialisation for movable objects.
|
||||||
|
template <typename IoObjectService>
|
||||||
|
class basic_io_object<IoObjectService, true>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef IoObjectService service_type;
|
||||||
|
typedef typename service_type::implementation_type implementation_type;
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
asio::io_context& get_io_context()
|
||||||
|
{
|
||||||
|
return service_->get_io_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
asio::io_context& get_io_service()
|
||||||
|
{
|
||||||
|
return service_->get_io_context();
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
typedef asio::io_context::executor_type executor_type;
|
||||||
|
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return service_->get_io_context().get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit basic_io_object(asio::io_context& io_context)
|
||||||
|
: service_(&asio::use_service<IoObjectService>(io_context))
|
||||||
|
{
|
||||||
|
service_->construct(implementation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_io_object(basic_io_object&& other)
|
||||||
|
: service_(&other.get_service())
|
||||||
|
{
|
||||||
|
service_->move_construct(implementation_, other.implementation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IoObjectService1>
|
||||||
|
basic_io_object(IoObjectService1& other_service,
|
||||||
|
typename IoObjectService1::implementation_type& other_implementation)
|
||||||
|
: service_(&asio::use_service<IoObjectService>(
|
||||||
|
other_service.get_io_context()))
|
||||||
|
{
|
||||||
|
service_->converting_move_construct(implementation_,
|
||||||
|
other_service, other_implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
~basic_io_object()
|
||||||
|
{
|
||||||
|
service_->destroy(implementation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_io_object& operator=(basic_io_object&& other)
|
||||||
|
{
|
||||||
|
service_->move_assign(implementation_,
|
||||||
|
*other.service_, other.implementation_);
|
||||||
|
service_ = other.service_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
service_type& get_service()
|
||||||
|
{
|
||||||
|
return *service_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const service_type& get_service() const
|
||||||
|
{
|
||||||
|
return *service_;
|
||||||
|
}
|
||||||
|
|
||||||
|
implementation_type& get_implementation()
|
||||||
|
{
|
||||||
|
return implementation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const implementation_type& get_implementation() const
|
||||||
|
{
|
||||||
|
return implementation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_io_object(const basic_io_object&);
|
||||||
|
void operator=(const basic_io_object&);
|
||||||
|
|
||||||
|
IoObjectService* service_;
|
||||||
|
implementation_type implementation_;
|
||||||
|
};
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_IO_OBJECT_HPP
|
689
lib/asio/include/asio/basic_random_access_file.hpp
Normal file
689
lib/asio/include/asio/basic_random_access_file.hpp
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
//
|
||||||
|
// basic_random_access_file.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
|
||||||
|
#define ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_FILE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/basic_file.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_random_access_file;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
|
||||||
|
|
||||||
|
/// Provides random-access file functionality.
|
||||||
|
/**
|
||||||
|
* The basic_random_access_file class template provides asynchronous and
|
||||||
|
* blocking random-access file functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* Synchronous @c read_some_at and @c write_some_at operations are thread safe
|
||||||
|
* with respect to each other, if the underlying operating system calls are
|
||||||
|
* also thread safe. This means that it is permitted to perform concurrent
|
||||||
|
* calls to these synchronous operations on a single file object. Other
|
||||||
|
* synchronous operations, such as @c open or @c close, are not thread safe.
|
||||||
|
*/
|
||||||
|
template <typename Executor>
|
||||||
|
class basic_random_access_file
|
||||||
|
: public basic_file<Executor>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the file type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The file type when rebound to the specified executor.
|
||||||
|
typedef basic_random_access_file<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a file.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef typename basic_file<Executor>::native_handle_type native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_random_access_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it. The file needs to
|
||||||
|
* be opened before data can be read from or or written to it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*/
|
||||||
|
explicit basic_random_access_file(const executor_type& ex)
|
||||||
|
: basic_file<Executor>(ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_random_access_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it. The file needs to
|
||||||
|
* be opened before data can be read from or or written to it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_random_access_file(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_random_access_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_random_access_file(const executor_type& ex,
|
||||||
|
const char* path, file_base::flags open_flags)
|
||||||
|
: basic_file<Executor>(ex, path, open_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_random_access_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_random_access_file(ExecutionContext& context,
|
||||||
|
const char* path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context, path, open_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_random_access_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_random_access_file(const executor_type& ex,
|
||||||
|
const std::string& path, file_base::flags open_flags)
|
||||||
|
: basic_file<Executor>(ex, path, open_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_random_access_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_random_access_file(ExecutionContext& context,
|
||||||
|
const std::string& path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context, path, open_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_random_access_file on an existing native file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a random-access file object to hold an
|
||||||
|
* existing native file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file The new underlying file implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_random_access_file(const executor_type& ex,
|
||||||
|
const native_handle_type& native_file)
|
||||||
|
: basic_file<Executor>(ex, native_file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_random_access_file on an existing native file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a random-access file object to hold an
|
||||||
|
* existing native file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file The new underlying file implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_random_access_file(ExecutionContext& context,
|
||||||
|
const native_handle_type& native_file,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context, native_file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_random_access_file from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a random-access file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_random_access_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_random_access_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_random_access_file(basic_random_access_file&& other) ASIO_NOEXCEPT
|
||||||
|
: basic_file<Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_random_access_file from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a random-access file from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_random_access_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_random_access_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_random_access_file& operator=(basic_random_access_file&& other)
|
||||||
|
{
|
||||||
|
basic_file<Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-construct a basic_random_access_file from a file of another executor
|
||||||
|
/// type.
|
||||||
|
/**
|
||||||
|
* This constructor moves a random-access file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_random_access_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_random_access_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
basic_random_access_file(basic_random_access_file<Executor1>&& other,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_random_access_file from a file of another executor
|
||||||
|
/// type.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a random-access file from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_random_access_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_random_access_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
basic_random_access_file&
|
||||||
|
>::type operator=(basic_random_access_file<Executor1>&& other)
|
||||||
|
{
|
||||||
|
basic_file<Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the file.
|
||||||
|
/**
|
||||||
|
* This function destroys the file, cancelling any outstanding asynchronous
|
||||||
|
* operations associated with the file as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_random_access_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the handle at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the random-access handle. The
|
||||||
|
* function call will block until one or more bytes of the data has been
|
||||||
|
* written successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be written.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the handle.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the end of the file was reached.
|
||||||
|
*
|
||||||
|
* @note The write_some_at operation may not write all of the data. Consider
|
||||||
|
* using the @ref write_at function if you need to ensure that all data is
|
||||||
|
* written before the blocking operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* handle.write_some_at(42, asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some_at(uint64_t offset,
|
||||||
|
const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().write_some_at(
|
||||||
|
this->impl_.get_implementation(), offset, buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "write_some_at");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the handle at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the random-access handle. The
|
||||||
|
* function call will block until one or more bytes of the data has been
|
||||||
|
* written successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be written.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the handle.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not write all of the data to the
|
||||||
|
* file. Consider using the @ref write_at function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some_at(uint64_t offset,
|
||||||
|
const ConstBufferSequence& buffers, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().write_some_at(
|
||||||
|
this->impl_.get_implementation(), offset, buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously write data to the random-access
|
||||||
|
* handle. It is an initiating function for an @ref asynchronous_operation,
|
||||||
|
* and always returns immediately.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be written.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the handle.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the write completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes written.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The write operation may not write all of the data to the file.
|
||||||
|
* Consider using the @ref async_write_at function if you need to ensure that
|
||||||
|
* all data is written before the asynchronous operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* handle.async_write_some_at(42, asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* This asynchronous operation supports cancellation for the following
|
||||||
|
* asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some_at(uint64_t offset,
|
||||||
|
const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WriteToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_write_some_at(this), token, offset, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the handle at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the random-access handle. The
|
||||||
|
* function call will block until one or more bytes of data has been read
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be read.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the end of the file was reached.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read_at function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* handle.read_some_at(42, asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some_at(uint64_t offset,
|
||||||
|
const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().read_some_at(
|
||||||
|
this->impl_.get_implementation(), offset, buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "read_some_at");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the handle at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the random-access handle. The
|
||||||
|
* function call will block until one or more bytes of data has been read
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be read.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read_at function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some_at(uint64_t offset,
|
||||||
|
const MutableBufferSequence& buffers, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().read_some_at(
|
||||||
|
this->impl_.get_implementation(), offset, buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read at the specified offset.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously read data from the random-access
|
||||||
|
* handle. It is an initiating function for an @ref asynchronous_operation,
|
||||||
|
* and always returns immediately.
|
||||||
|
*
|
||||||
|
* @param offset The offset at which the data will be read.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the read completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes read.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The read operation may not read all of the requested number of bytes.
|
||||||
|
* Consider using the @ref async_read_at function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the asynchronous operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* handle.async_read_some_at(42, asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* This asynchronous operation supports cancellation for the following
|
||||||
|
* asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some_at(uint64_t offset,
|
||||||
|
const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_read_some_at(this), token, offset, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_random_access_file(const basic_random_access_file&) ASIO_DELETED;
|
||||||
|
basic_random_access_file& operator=(
|
||||||
|
const basic_random_access_file&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_write_some_at
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_write_some_at(basic_random_access_file* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WriteHandler, typename ConstBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
|
||||||
|
uint64_t offset, const ConstBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WriteHandler.
|
||||||
|
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_write_some_at(
|
||||||
|
self_->impl_.get_implementation(), offset, buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_random_access_file* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class initiate_async_read_some_at
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_read_some_at(basic_random_access_file* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReadHandler, typename MutableBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
|
||||||
|
uint64_t offset, const MutableBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a ReadHandler.
|
||||||
|
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_read_some_at(
|
||||||
|
self_->impl_.get_implementation(), offset, buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_random_access_file* self_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_FILE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
|
1342
lib/asio/include/asio/basic_raw_socket.hpp
Normal file
1342
lib/asio/include/asio/basic_raw_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
529
lib/asio/include/asio/basic_readable_pipe.hpp
Normal file
529
lib/asio/include/asio/basic_readable_pipe.hpp
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
//
|
||||||
|
// basic_readable_pipe.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_READABLE_PIPE_HPP
|
||||||
|
#define ASIO_BASIC_READABLE_PIPE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_PIPE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
# include "asio/detail/win_iocp_handle_service.hpp"
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
# include "asio/detail/io_uring_descriptor_service.hpp"
|
||||||
|
#else
|
||||||
|
# include "asio/detail/reactive_descriptor_service.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Provides pipe functionality.
|
||||||
|
/**
|
||||||
|
* The basic_readable_pipe class provides a wrapper over pipe
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*/
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_readable_pipe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the pipe type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The pipe type when rebound to the specified executor.
|
||||||
|
typedef basic_readable_pipe<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a pipe.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IOCP)
|
||||||
|
typedef detail::win_iocp_handle_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
typedef detail::io_uring_descriptor_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef detail::reactive_descriptor_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// A basic_readable_pipe is always the lowest layer.
|
||||||
|
typedef basic_readable_pipe lowest_layer_type;
|
||||||
|
|
||||||
|
/// Construct a basic_readable_pipe without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe without opening it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the pipe will use, by default, to dispatch
|
||||||
|
* handlers for any asynchronous operations performed on the pipe.
|
||||||
|
*/
|
||||||
|
explicit basic_readable_pipe(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_readable_pipe without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe without opening it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the pipe will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the pipe.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_readable_pipe(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_readable_pipe on an existing native pipe.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe object to hold an existing native
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the pipe will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_readable_pipe(const executor_type& ex,
|
||||||
|
const native_handle_type& native_pipe)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_readable_pipe on an existing native pipe.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe object to hold an existing native
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the pipe will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_readable_pipe(ExecutionContext& context,
|
||||||
|
const native_handle_type& native_pipe,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_readable_pipe from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a pipe from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_readable_pipe object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_readable_pipe(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_readable_pipe(basic_readable_pipe&& other)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_readable_pipe from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a pipe from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_readable_pipe object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_readable_pipe(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_readable_pipe& operator=(basic_readable_pipe&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the pipe.
|
||||||
|
/**
|
||||||
|
* This function destroys the pipe, cancelling any outstanding
|
||||||
|
* asynchronous wait operations associated with the pipe as if by
|
||||||
|
* calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_readable_pipe()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_readable_pipe cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||||
|
* is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a const reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_readable_pipe cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A const reference to the lowest layer in the stack of layers.
|
||||||
|
* Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native pipe to the pipe.
|
||||||
|
/*
|
||||||
|
* This function opens the pipe to hold an existing native pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void assign(const native_handle_type& native_pipe)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native pipe to the pipe.
|
||||||
|
/*
|
||||||
|
* This function opens the pipe to hold an existing native pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine whether the pipe is open.
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().is_open(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to close the pipe. Any asynchronous read operations
|
||||||
|
* will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to close the pipe. Any asynchronous read operations
|
||||||
|
* will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the native pipe representation.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the underlying representation of the
|
||||||
|
* pipe. This is intended to allow access to native pipe
|
||||||
|
* functionality that is not otherwise provided.
|
||||||
|
*/
|
||||||
|
native_handle_type native_handle()
|
||||||
|
{
|
||||||
|
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the pipe.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read operations to finish
|
||||||
|
* immediately, and the handlers for cancelled operations will be passed the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the pipe.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read operations to finish
|
||||||
|
* immediately, and the handlers for cancelled operations will be passed the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the pipe. The function call will
|
||||||
|
* block until one or more bytes of data has been read successfully, or until
|
||||||
|
* an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_readable_pipe.read_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().read_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "read_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the pipe. The function call will
|
||||||
|
* block until one or more bytes of data has been read successfully, or until
|
||||||
|
* an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().read_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously read data from the pipe. It is an
|
||||||
|
* initiating function for an @ref asynchronous_operation, and always returns
|
||||||
|
* immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the read completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes read.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The read operation may not read all of the requested number of bytes.
|
||||||
|
* Consider using the @ref async_read function if you need to ensure that the
|
||||||
|
* requested amount of data is read before the asynchronous operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_readable_pipe.async_read_some(
|
||||||
|
* asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_read_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_readable_pipe(const basic_readable_pipe&) ASIO_DELETED;
|
||||||
|
basic_readable_pipe& operator=(const basic_readable_pipe&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_read_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_read_some(basic_readable_pipe* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReadHandler, typename MutableBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
|
||||||
|
const MutableBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a ReadHandler.
|
||||||
|
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_read_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_readable_pipe* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;
|
||||||
|
#else
|
||||||
|
detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_PIPE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_READABLE_PIPE_HPP
|
816
lib/asio/include/asio/basic_seq_packet_socket.hpp
Normal file
816
lib/asio/include/asio/basic_seq_packet_socket.hpp
Normal file
@ -0,0 +1,816 @@
|
|||||||
|
//
|
||||||
|
// basic_seq_packet_socket.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
|
||||||
|
#define ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/basic_socket.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Protocol, typename Executor = any_io_executor>
|
||||||
|
class basic_seq_packet_socket;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
|
||||||
|
|
||||||
|
/// Provides sequenced packet socket functionality.
|
||||||
|
/**
|
||||||
|
* The basic_seq_packet_socket class template provides asynchronous and blocking
|
||||||
|
* sequenced packet socket functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* Synchronous @c send, @c receive, and @c connect operations are thread safe
|
||||||
|
* with respect to each other, if the underlying operating system calls are
|
||||||
|
* also thread safe. This means that it is permitted to perform concurrent
|
||||||
|
* calls to these synchronous operations on a single socket object. Other
|
||||||
|
* synchronous operations, such as @c open or @c close, are not thread safe.
|
||||||
|
*/
|
||||||
|
template <typename Protocol, typename Executor>
|
||||||
|
class basic_seq_packet_socket
|
||||||
|
: public basic_socket<Protocol, Executor>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the socket type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The socket type when rebound to the specified executor.
|
||||||
|
typedef basic_seq_packet_socket<Protocol, Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a socket.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef typename basic_socket<Protocol,
|
||||||
|
Executor>::native_handle_type native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// The protocol type.
|
||||||
|
typedef Protocol protocol_type;
|
||||||
|
|
||||||
|
/// The endpoint type.
|
||||||
|
typedef typename Protocol::endpoint endpoint_type;
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket without opening it. The
|
||||||
|
* socket needs to be opened and then connected or accepted before data can
|
||||||
|
* be sent or received on it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the socket will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||||
|
*/
|
||||||
|
explicit basic_seq_packet_socket(const executor_type& ex)
|
||||||
|
: basic_socket<Protocol, Executor>(ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket without opening it. The
|
||||||
|
* socket needs to be opened and then connected or accepted before data can
|
||||||
|
* be sent or received on it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the socket.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_seq_packet_socket(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: basic_socket<Protocol, Executor>(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_seq_packet_socket.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a sequenced_packet socket. The socket
|
||||||
|
* needs to be connected or accepted before data can be sent or received on
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the socket will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param protocol An object specifying protocol parameters to be used.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_seq_packet_socket(const executor_type& ex,
|
||||||
|
const protocol_type& protocol)
|
||||||
|
: basic_socket<Protocol, Executor>(ex, protocol)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_seq_packet_socket.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a sequenced_packet socket. The socket
|
||||||
|
* needs to be connected or accepted before data can be sent or received on
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param protocol An object specifying protocol parameters to be used.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_seq_packet_socket(ExecutionContext& context,
|
||||||
|
const protocol_type& protocol,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_socket<Protocol, Executor>(context, protocol)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket, opening it and binding it to the
|
||||||
|
/// given local endpoint.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket and automatically opens
|
||||||
|
* it bound to the specified endpoint on the local machine. The protocol used
|
||||||
|
* is the protocol associated with the given endpoint.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the socket will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param endpoint An endpoint on the local machine to which the sequenced
|
||||||
|
* packet socket will be bound.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_seq_packet_socket(const executor_type& ex,
|
||||||
|
const endpoint_type& endpoint)
|
||||||
|
: basic_socket<Protocol, Executor>(ex, endpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket, opening it and binding it to the
|
||||||
|
/// given local endpoint.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket and automatically opens
|
||||||
|
* it bound to the specified endpoint on the local machine. The protocol used
|
||||||
|
* is the protocol associated with the given endpoint.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param endpoint An endpoint on the local machine to which the sequenced
|
||||||
|
* packet socket will be bound.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_seq_packet_socket(ExecutionContext& context,
|
||||||
|
const endpoint_type& endpoint,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket on an existing native socket.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket object to hold an
|
||||||
|
* existing native socket.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the socket will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param protocol An object specifying protocol parameters to be used.
|
||||||
|
*
|
||||||
|
* @param native_socket The new underlying socket implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_seq_packet_socket(const executor_type& ex,
|
||||||
|
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||||
|
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_seq_packet_socket on an existing native socket.
|
||||||
|
/**
|
||||||
|
* This constructor creates a sequenced packet socket object to hold an
|
||||||
|
* existing native socket.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the socket.
|
||||||
|
*
|
||||||
|
* @param protocol An object specifying protocol parameters to be used.
|
||||||
|
*
|
||||||
|
* @param native_socket The new underlying socket implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_seq_packet_socket(ExecutionContext& context,
|
||||||
|
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_seq_packet_socket from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a sequenced packet socket from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_seq_packet_socket object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_seq_packet_socket(basic_seq_packet_socket&& other) ASIO_NOEXCEPT
|
||||||
|
: basic_socket<Protocol, Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_seq_packet_socket from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a sequenced packet socket from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_seq_packet_socket object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
|
||||||
|
{
|
||||||
|
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-construct a basic_seq_packet_socket from a socket of another protocol
|
||||||
|
/// type.
|
||||||
|
/**
|
||||||
|
* This constructor moves a sequenced packet socket from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_seq_packet_socket object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Protocol1, typename Executor1>
|
||||||
|
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Protocol1, Protocol>::value
|
||||||
|
&& is_convertible<Executor1, Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
: basic_socket<Protocol, Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_seq_packet_socket from a socket of another protocol
|
||||||
|
/// type.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a sequenced packet socket from one object to
|
||||||
|
* another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_seq_packet_socket object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Protocol1, typename Executor1>
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Protocol1, Protocol>::value
|
||||||
|
&& is_convertible<Executor1, Executor>::value,
|
||||||
|
basic_seq_packet_socket&
|
||||||
|
>::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
|
||||||
|
{
|
||||||
|
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the socket.
|
||||||
|
/**
|
||||||
|
* This function destroys the socket, cancelling any outstanding asynchronous
|
||||||
|
* operations associated with the socket as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_seq_packet_socket()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send some data on the socket.
|
||||||
|
/**
|
||||||
|
* This function is used to send data on the sequenced packet socket. The
|
||||||
|
* function call will block until the data has been sent successfully, or an
|
||||||
|
* until error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be sent on the socket.
|
||||||
|
*
|
||||||
|
* @param flags Flags specifying how the send call is to be made.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes sent.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To send a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* socket.send(asio::buffer(data, size), 0);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on sending multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t send(const ConstBufferSequence& buffers,
|
||||||
|
socket_base::message_flags flags)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().send(
|
||||||
|
this->impl_.get_implementation(), buffers, flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "send");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send some data on the socket.
|
||||||
|
/**
|
||||||
|
* This function is used to send data on the sequenced packet socket. The
|
||||||
|
* function call will block the data has been sent successfully, or an until
|
||||||
|
* error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be sent on the socket.
|
||||||
|
*
|
||||||
|
* @param flags Flags specifying how the send call is to be made.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes sent. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The send operation may not transmit all of the data to the peer.
|
||||||
|
* Consider using the @ref write function if you need to ensure that all data
|
||||||
|
* is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t send(const ConstBufferSequence& buffers,
|
||||||
|
socket_base::message_flags flags, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().send(
|
||||||
|
this->impl_.get_implementation(), buffers, flags, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous send.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously send data on the sequenced packet
|
||||||
|
* socket. It is an initiating function for an @ref asynchronous_operation,
|
||||||
|
* and always returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be sent on the socket. Although
|
||||||
|
* the buffers object may be copied as necessary, ownership of the underlying
|
||||||
|
* memory blocks is retained by the caller, which must guarantee that they
|
||||||
|
* remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param flags Flags specifying how the send call is to be made.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the send completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes sent.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To send a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* socket.async_send(asio::buffer(data, size), 0, handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on sending multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_send(const ConstBufferSequence& buffers,
|
||||||
|
socket_base::message_flags flags,
|
||||||
|
ASIO_MOVE_ARG(WriteToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WriteToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_send(this), token, buffers, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive some data on the socket.
|
||||||
|
/**
|
||||||
|
* This function is used to receive data on the sequenced packet socket. The
|
||||||
|
* function call will block until data has been received successfully, or
|
||||||
|
* until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be received.
|
||||||
|
*
|
||||||
|
* @param out_flags After the receive call completes, contains flags
|
||||||
|
* associated with the received data. For example, if the
|
||||||
|
* socket_base::message_end_of_record bit is set then the received data marks
|
||||||
|
* the end of a record.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes received.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To receive into a single data buffer use the @ref buffer function as
|
||||||
|
* follows:
|
||||||
|
* @code
|
||||||
|
* socket.receive(asio::buffer(data, size), out_flags);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on receiving into
|
||||||
|
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t receive(const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags& out_flags)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().receive_with_flags(
|
||||||
|
this->impl_.get_implementation(), buffers, 0, out_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "receive");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive some data on the socket.
|
||||||
|
/**
|
||||||
|
* This function is used to receive data on the sequenced packet socket. The
|
||||||
|
* function call will block until data has been received successfully, or
|
||||||
|
* until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be received.
|
||||||
|
*
|
||||||
|
* @param in_flags Flags specifying how the receive call is to be made.
|
||||||
|
*
|
||||||
|
* @param out_flags After the receive call completes, contains flags
|
||||||
|
* associated with the received data. For example, if the
|
||||||
|
* socket_base::message_end_of_record bit is set then the received data marks
|
||||||
|
* the end of a record.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes received.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @note The receive operation may not receive all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that the
|
||||||
|
* requested amount of data is read before the blocking operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To receive into a single data buffer use the @ref buffer function as
|
||||||
|
* follows:
|
||||||
|
* @code
|
||||||
|
* socket.receive(asio::buffer(data, size), 0, out_flags);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on receiving into
|
||||||
|
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t receive(const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags in_flags,
|
||||||
|
socket_base::message_flags& out_flags)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().receive_with_flags(
|
||||||
|
this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "receive");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive some data on a connected socket.
|
||||||
|
/**
|
||||||
|
* This function is used to receive data on the sequenced packet socket. The
|
||||||
|
* function call will block until data has been received successfully, or
|
||||||
|
* until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be received.
|
||||||
|
*
|
||||||
|
* @param in_flags Flags specifying how the receive call is to be made.
|
||||||
|
*
|
||||||
|
* @param out_flags After the receive call completes, contains flags
|
||||||
|
* associated with the received data. For example, if the
|
||||||
|
* socket_base::message_end_of_record bit is set then the received data marks
|
||||||
|
* the end of a record.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes received. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The receive operation may not receive all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that the
|
||||||
|
* requested amount of data is read before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t receive(const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags in_flags,
|
||||||
|
socket_base::message_flags& out_flags, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().receive_with_flags(
|
||||||
|
this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous receive.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously receive data from the sequenced
|
||||||
|
* packet socket. It is an initiating function for an @ref
|
||||||
|
* asynchronous_operation, and always returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be received.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param out_flags Once the asynchronous operation completes, contains flags
|
||||||
|
* associated with the received data. For example, if the
|
||||||
|
* socket_base::message_end_of_record bit is set then the received data marks
|
||||||
|
* the end of a record. The caller must guarantee that the referenced
|
||||||
|
* variable remains valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the receive completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes received.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To receive into a single data buffer use the @ref buffer function as
|
||||||
|
* follows:
|
||||||
|
* @code
|
||||||
|
* socket.async_receive(asio::buffer(data, size), out_flags, handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on receiving into
|
||||||
|
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_receive(const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags& out_flags,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_receive_with_flags(this), token,
|
||||||
|
buffers, socket_base::message_flags(0), &out_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous receive.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously receive data from the sequenced
|
||||||
|
* data socket. It is an initiating function for an @ref
|
||||||
|
* asynchronous_operation, and always returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be received.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param in_flags Flags specifying how the receive call is to be made.
|
||||||
|
*
|
||||||
|
* @param out_flags Once the asynchronous operation completes, contains flags
|
||||||
|
* associated with the received data. For example, if the
|
||||||
|
* socket_base::message_end_of_record bit is set then the received data marks
|
||||||
|
* the end of a record. The caller must guarantee that the referenced
|
||||||
|
* variable remains valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the receive completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes received.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To receive into a single data buffer use the @ref buffer function as
|
||||||
|
* follows:
|
||||||
|
* @code
|
||||||
|
* socket.async_receive(
|
||||||
|
* asio::buffer(data, size),
|
||||||
|
* 0, out_flags, handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on receiving into
|
||||||
|
* multiple buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_receive(const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags in_flags,
|
||||||
|
socket_base::message_flags& out_flags,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_receive_with_flags(this),
|
||||||
|
token, buffers, in_flags, &out_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_seq_packet_socket(const basic_seq_packet_socket&) ASIO_DELETED;
|
||||||
|
basic_seq_packet_socket& operator=(
|
||||||
|
const basic_seq_packet_socket&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_send
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_send(basic_seq_packet_socket* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WriteHandler, typename ConstBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
|
||||||
|
const ConstBufferSequence& buffers,
|
||||||
|
socket_base::message_flags flags) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WriteHandler.
|
||||||
|
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_send(
|
||||||
|
self_->impl_.get_implementation(), buffers, flags,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_seq_packet_socket* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class initiate_async_receive_with_flags
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_receive_with_flags(basic_seq_packet_socket* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReadHandler, typename MutableBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
|
||||||
|
const MutableBufferSequence& buffers,
|
||||||
|
socket_base::message_flags in_flags,
|
||||||
|
socket_base::message_flags* out_flags) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a ReadHandler.
|
||||||
|
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_receive_with_flags(
|
||||||
|
self_->impl_.get_implementation(), buffers, in_flags,
|
||||||
|
*out_flags, handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_seq_packet_socket* self_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
|
939
lib/asio/include/asio/basic_serial_port.hpp
Normal file
939
lib/asio/include/asio/basic_serial_port.hpp
Normal file
@ -0,0 +1,939 @@
|
|||||||
|
//
|
||||||
|
// basic_serial_port.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_SERIAL_PORT_HPP
|
||||||
|
#define ASIO_BASIC_SERIAL_PORT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_SERIAL_PORT) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/serial_port_base.hpp"
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
# include "asio/detail/win_iocp_serial_port_service.hpp"
|
||||||
|
#else
|
||||||
|
# include "asio/detail/posix_serial_port_service.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Provides serial port functionality.
|
||||||
|
/**
|
||||||
|
* The basic_serial_port class provides a wrapper over serial port
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*/
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_serial_port
|
||||||
|
: public serial_port_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the serial port type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The serial port type when rebound to the specified executor.
|
||||||
|
typedef basic_serial_port<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a serial port.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IOCP)
|
||||||
|
typedef detail::win_iocp_serial_port_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef detail::posix_serial_port_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// A basic_basic_serial_port is always the lowest layer.
|
||||||
|
typedef basic_serial_port lowest_layer_type;
|
||||||
|
|
||||||
|
/// Construct a basic_serial_port without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a serial port without opening it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the serial port will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* serial port.
|
||||||
|
*/
|
||||||
|
explicit basic_serial_port(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_serial_port without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a serial port without opening it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the serial port will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the serial port.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_serial_port(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_serial_port.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a serial port for the specified device
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the serial port will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* serial port.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name for this serial
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
basic_serial_port(const executor_type& ex, const char* device)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_serial_port.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a serial port for the specified device
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the serial port will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the serial port.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name for this serial
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_serial_port(ExecutionContext& context, const char* device,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_serial_port.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a serial port for the specified device
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the serial port will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* serial port.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name for this serial
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
basic_serial_port(const executor_type& ex, const std::string& device)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_serial_port.
|
||||||
|
/**
|
||||||
|
* This constructor creates and opens a serial port for the specified device
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the serial port will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the serial port.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name for this serial
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_serial_port(ExecutionContext& context, const std::string& device,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_serial_port on an existing native serial port.
|
||||||
|
/**
|
||||||
|
* This constructor creates a serial port object to hold an existing native
|
||||||
|
* serial port.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the serial port will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* serial port.
|
||||||
|
*
|
||||||
|
* @param native_serial_port A native serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_serial_port(const executor_type& ex,
|
||||||
|
const native_handle_type& native_serial_port)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_serial_port, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_serial_port on an existing native serial port.
|
||||||
|
/**
|
||||||
|
* This constructor creates a serial port object to hold an existing native
|
||||||
|
* serial port.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the serial port will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the serial port.
|
||||||
|
*
|
||||||
|
* @param native_serial_port A native serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_serial_port(ExecutionContext& context,
|
||||||
|
const native_handle_type& native_serial_port,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_serial_port, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_serial_port from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a serial port from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_serial_port object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_serial_port(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_serial_port(basic_serial_port&& other)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_serial_port from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a serial port from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_serial_port object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_serial_port(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_serial_port& operator=(basic_serial_port&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the serial port.
|
||||||
|
/**
|
||||||
|
* This function destroys the serial port, cancelling any outstanding
|
||||||
|
* asynchronous wait operations associated with the serial port as if by
|
||||||
|
* calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_serial_port()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||||
|
* is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a const reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A const reference to the lowest layer in the stack of layers.
|
||||||
|
* Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the serial port using the specified device name.
|
||||||
|
/**
|
||||||
|
* This function opens the serial port for the specified device name.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void open(const std::string& device)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open the serial port using the specified device name.
|
||||||
|
/**
|
||||||
|
* This function opens the serial port using the given platform-specific
|
||||||
|
* device name.
|
||||||
|
*
|
||||||
|
* @param device The platform-specific device name.
|
||||||
|
*
|
||||||
|
* @param ec Set the indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID open(const std::string& device,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native serial port to the serial port.
|
||||||
|
/*
|
||||||
|
* This function opens the serial port to hold an existing native serial port.
|
||||||
|
*
|
||||||
|
* @param native_serial_port A native serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void assign(const native_handle_type& native_serial_port)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_serial_port, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native serial port to the serial port.
|
||||||
|
/*
|
||||||
|
* This function opens the serial port to hold an existing native serial port.
|
||||||
|
*
|
||||||
|
* @param native_serial_port A native serial port.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_serial_port, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine whether the serial port is open.
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().is_open(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to close the serial port. Any asynchronous read or
|
||||||
|
* write operations will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to close the serial port. Any asynchronous read or
|
||||||
|
* write operations will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the native serial port representation.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the underlying representation of the
|
||||||
|
* serial port. This is intended to allow access to native serial port
|
||||||
|
* functionality that is not otherwise provided.
|
||||||
|
*/
|
||||||
|
native_handle_type native_handle()
|
||||||
|
{
|
||||||
|
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the serial port.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read or write operations
|
||||||
|
* to finish immediately, and the handlers for cancelled operations will be
|
||||||
|
* passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the serial port.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous read or write operations
|
||||||
|
* to finish immediately, and the handlers for cancelled operations will be
|
||||||
|
* passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a break sequence to the serial port.
|
||||||
|
/**
|
||||||
|
* This function causes a break sequence of platform-specific duration to be
|
||||||
|
* sent out the serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void send_break()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().send_break(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "send_break");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a break sequence to the serial port.
|
||||||
|
/**
|
||||||
|
* This function causes a break sequence of platform-specific duration to be
|
||||||
|
* sent out the serial port.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID send_break(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().send_break(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set an option on the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to set an option on the serial port.
|
||||||
|
*
|
||||||
|
* @param option The option value to be set on the serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @sa SettableSerialPortOption @n
|
||||||
|
* asio::serial_port_base::baud_rate @n
|
||||||
|
* asio::serial_port_base::flow_control @n
|
||||||
|
* asio::serial_port_base::parity @n
|
||||||
|
* asio::serial_port_base::stop_bits @n
|
||||||
|
* asio::serial_port_base::character_size
|
||||||
|
*/
|
||||||
|
template <typename SettableSerialPortOption>
|
||||||
|
void set_option(const SettableSerialPortOption& option)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
|
||||||
|
asio::detail::throw_error(ec, "set_option");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set an option on the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to set an option on the serial port.
|
||||||
|
*
|
||||||
|
* @param option The option value to be set on the serial port.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @sa SettableSerialPortOption @n
|
||||||
|
* asio::serial_port_base::baud_rate @n
|
||||||
|
* asio::serial_port_base::flow_control @n
|
||||||
|
* asio::serial_port_base::parity @n
|
||||||
|
* asio::serial_port_base::stop_bits @n
|
||||||
|
* asio::serial_port_base::character_size
|
||||||
|
*/
|
||||||
|
template <typename SettableSerialPortOption>
|
||||||
|
ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an option from the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to get the current value of an option on the serial
|
||||||
|
* port.
|
||||||
|
*
|
||||||
|
* @param option The option value to be obtained from the serial port.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @sa GettableSerialPortOption @n
|
||||||
|
* asio::serial_port_base::baud_rate @n
|
||||||
|
* asio::serial_port_base::flow_control @n
|
||||||
|
* asio::serial_port_base::parity @n
|
||||||
|
* asio::serial_port_base::stop_bits @n
|
||||||
|
* asio::serial_port_base::character_size
|
||||||
|
*/
|
||||||
|
template <typename GettableSerialPortOption>
|
||||||
|
void get_option(GettableSerialPortOption& option) const
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
|
||||||
|
asio::detail::throw_error(ec, "get_option");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an option from the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to get the current value of an option on the serial
|
||||||
|
* port.
|
||||||
|
*
|
||||||
|
* @param option The option value to be obtained from the serial port.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @sa GettableSerialPortOption @n
|
||||||
|
* asio::serial_port_base::baud_rate @n
|
||||||
|
* asio::serial_port_base::flow_control @n
|
||||||
|
* asio::serial_port_base::parity @n
|
||||||
|
* asio::serial_port_base::stop_bits @n
|
||||||
|
* asio::serial_port_base::character_size
|
||||||
|
*/
|
||||||
|
template <typename GettableSerialPortOption>
|
||||||
|
ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
|
||||||
|
asio::error_code& ec) const
|
||||||
|
{
|
||||||
|
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the serial port. The function call
|
||||||
|
* will block until one or more bytes of the data has been written
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the serial port.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_serial_port.write_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().write_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "write_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the serial port. The function call
|
||||||
|
* will block until one or more bytes of the data has been written
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the serial port.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().write_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously write data to the serial port.
|
||||||
|
* It is an initiating function for an @ref asynchronous_operation, and always
|
||||||
|
* returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the serial port.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the write completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes written.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The write operation may not transmit all of the data to the peer.
|
||||||
|
* Consider using the @ref async_write function if you need to ensure that all
|
||||||
|
* data is written before the asynchronous operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_serial_port.async_write_some(
|
||||||
|
* asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WriteToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_write_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the serial port. The function
|
||||||
|
* call will block until one or more bytes of data has been read successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_serial_port.read_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().read_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "read_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the serial port.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the serial port. The function
|
||||||
|
* call will block until one or more bytes of data has been read successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().read_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously read data from the serial port.
|
||||||
|
* It is an initiating function for an @ref asynchronous_operation, and always
|
||||||
|
* returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the read completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes read.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The read operation may not read all of the requested number of bytes.
|
||||||
|
* Consider using the @ref async_read function if you need to ensure that the
|
||||||
|
* requested amount of data is read before the asynchronous operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* basic_serial_port.async_read_some(
|
||||||
|
* asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_read_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_serial_port(const basic_serial_port&) ASIO_DELETED;
|
||||||
|
basic_serial_port& operator=(const basic_serial_port&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_write_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_write_some(basic_serial_port* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WriteHandler, typename ConstBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
|
||||||
|
const ConstBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WriteHandler.
|
||||||
|
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_write_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_serial_port* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class initiate_async_read_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_read_some(basic_serial_port* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReadHandler, typename MutableBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
|
||||||
|
const MutableBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a ReadHandler.
|
||||||
|
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_read_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_serial_port* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_;
|
||||||
|
#else
|
||||||
|
detail::io_object_impl<detail::posix_serial_port_service, Executor> impl_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_SERIAL_PORT)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_SERIAL_PORT_HPP
|
592
lib/asio/include/asio/basic_signal_set.hpp
Normal file
592
lib/asio/include/asio/basic_signal_set.hpp
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
//
|
||||||
|
// basic_signal_set.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_SIGNAL_SET_HPP
|
||||||
|
#define ASIO_BASIC_SIGNAL_SET_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/signal_set_service.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Provides signal functionality.
|
||||||
|
/**
|
||||||
|
* The basic_signal_set class provides the ability to perform an asynchronous
|
||||||
|
* wait for one or more signals to occur.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* Performing an asynchronous wait:
|
||||||
|
* @code
|
||||||
|
* void handler(
|
||||||
|
* const asio::error_code& error,
|
||||||
|
* int signal_number)
|
||||||
|
* {
|
||||||
|
* if (!error)
|
||||||
|
* {
|
||||||
|
* // A signal occurred.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* // Construct a signal set registered for process termination.
|
||||||
|
* asio::signal_set signals(my_context, SIGINT, SIGTERM);
|
||||||
|
*
|
||||||
|
* // Start an asynchronous wait for one of the signals to occur.
|
||||||
|
* signals.async_wait(handler);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Queueing of signal notifications
|
||||||
|
*
|
||||||
|
* If a signal is registered with a signal_set, and the signal occurs when
|
||||||
|
* there are no waiting handlers, then the signal notification is queued. The
|
||||||
|
* next async_wait operation on that signal_set will dequeue the notification.
|
||||||
|
* If multiple notifications are queued, subsequent async_wait operations
|
||||||
|
* dequeue them one at a time. Signal notifications are dequeued in order of
|
||||||
|
* ascending signal number.
|
||||||
|
*
|
||||||
|
* If a signal number is removed from a signal_set (using the @c remove or @c
|
||||||
|
* erase member functions) then any queued notifications for that signal are
|
||||||
|
* discarded.
|
||||||
|
*
|
||||||
|
* @par Multiple registration of signals
|
||||||
|
*
|
||||||
|
* The same signal number may be registered with different signal_set objects.
|
||||||
|
* When the signal occurs, one handler is called for each signal_set object.
|
||||||
|
*
|
||||||
|
* Note that multiple registration only works for signals that are registered
|
||||||
|
* using Asio. The application must not also register a signal handler using
|
||||||
|
* functions such as @c signal() or @c sigaction().
|
||||||
|
*
|
||||||
|
* @par Signal masking on POSIX platforms
|
||||||
|
*
|
||||||
|
* POSIX allows signals to be blocked using functions such as @c sigprocmask()
|
||||||
|
* and @c pthread_sigmask(). For signals to be delivered, programs must ensure
|
||||||
|
* that any signals registered using signal_set objects are unblocked in at
|
||||||
|
* least one thread.
|
||||||
|
*/
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_signal_set
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the signal set type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The signal set type when rebound to the specified executor.
|
||||||
|
typedef basic_signal_set<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Construct a signal set without adding any signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set without registering for any signals.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the signal set will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* signal set.
|
||||||
|
*/
|
||||||
|
explicit basic_signal_set(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set without adding any signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set without registering for any signals.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the signal set will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the signal set.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_signal_set(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add one signal.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for one signal.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the signal set will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(ex);
|
||||||
|
* signals.add(signal_number_1); @endcode
|
||||||
|
*/
|
||||||
|
basic_signal_set(const executor_type& ex, int signal_number_1)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add one signal.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for one signal.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the signal set will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(context);
|
||||||
|
* signals.add(signal_number_1); @endcode
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add two signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for two signals.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the signal set will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The first signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_2 The second signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(ex);
|
||||||
|
* signals.add(signal_number_1);
|
||||||
|
* signals.add(signal_number_2); @endcode
|
||||||
|
*/
|
||||||
|
basic_signal_set(const executor_type& ex, int signal_number_1,
|
||||||
|
int signal_number_2)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add two signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for two signals.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the signal set will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The first signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_2 The second signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(context);
|
||||||
|
* signals.add(signal_number_1);
|
||||||
|
* signals.add(signal_number_2); @endcode
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||||
|
int signal_number_2,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add three signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for three signals.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the signal set will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The first signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_2 The second signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_3 The third signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(ex);
|
||||||
|
* signals.add(signal_number_1);
|
||||||
|
* signals.add(signal_number_2);
|
||||||
|
* signals.add(signal_number_3); @endcode
|
||||||
|
*/
|
||||||
|
basic_signal_set(const executor_type& ex, int signal_number_1,
|
||||||
|
int signal_number_2, int signal_number_3)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a signal set and add three signals.
|
||||||
|
/**
|
||||||
|
* This constructor creates a signal set and registers for three signals.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the signal set will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the signal set.
|
||||||
|
*
|
||||||
|
* @param signal_number_1 The first signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_2 The second signal number to be added.
|
||||||
|
*
|
||||||
|
* @param signal_number_3 The third signal number to be added.
|
||||||
|
*
|
||||||
|
* @note This constructor is equivalent to performing:
|
||||||
|
* @code asio::signal_set signals(context);
|
||||||
|
* signals.add(signal_number_1);
|
||||||
|
* signals.add(signal_number_2);
|
||||||
|
* signals.add(signal_number_3); @endcode
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||||
|
int signal_number_2, int signal_number_3,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destroys the signal set.
|
||||||
|
/**
|
||||||
|
* This function destroys the signal set, cancelling any outstanding
|
||||||
|
* asynchronous wait operations associated with the signal set as if by
|
||||||
|
* calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_signal_set()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a signal to a signal_set.
|
||||||
|
/**
|
||||||
|
* This function adds the specified signal to the set. It has no effect if the
|
||||||
|
* signal is already in the set.
|
||||||
|
*
|
||||||
|
* @param signal_number The signal to be added to the set.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void add(int signal_number)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
|
||||||
|
asio::detail::throw_error(ec, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a signal to a signal_set.
|
||||||
|
/**
|
||||||
|
* This function adds the specified signal to the set. It has no effect if the
|
||||||
|
* signal is already in the set.
|
||||||
|
*
|
||||||
|
* @param signal_number The signal to be added to the set.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID add(int signal_number,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a signal from a signal_set.
|
||||||
|
/**
|
||||||
|
* This function removes the specified signal from the set. It has no effect
|
||||||
|
* if the signal is not in the set.
|
||||||
|
*
|
||||||
|
* @param signal_number The signal to be removed from the set.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note Removes any notifications that have been queued for the specified
|
||||||
|
* signal number.
|
||||||
|
*/
|
||||||
|
void remove(int signal_number)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
|
||||||
|
asio::detail::throw_error(ec, "remove");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a signal from a signal_set.
|
||||||
|
/**
|
||||||
|
* This function removes the specified signal from the set. It has no effect
|
||||||
|
* if the signal is not in the set.
|
||||||
|
*
|
||||||
|
* @param signal_number The signal to be removed from the set.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @note Removes any notifications that have been queued for the specified
|
||||||
|
* signal number.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID remove(int signal_number,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all signals from a signal_set.
|
||||||
|
/**
|
||||||
|
* This function removes all signals from the set. It has no effect if the set
|
||||||
|
* is already empty.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note Removes all queued notifications.
|
||||||
|
*/
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().clear(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "clear");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all signals from a signal_set.
|
||||||
|
/**
|
||||||
|
* This function removes all signals from the set. It has no effect if the set
|
||||||
|
* is already empty.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @note Removes all queued notifications.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID clear(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().clear(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all operations associated with the signal set.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the signal set. The handler for each cancelled
|
||||||
|
* operation will be invoked with the asio::error::operation_aborted
|
||||||
|
* error code.
|
||||||
|
*
|
||||||
|
* Cancellation does not alter the set of registered signals.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If a registered signal occurred before cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all operations associated with the signal set.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the signal set. The handler for each cancelled
|
||||||
|
* operation will be invoked with the asio::error::operation_aborted
|
||||||
|
* error code.
|
||||||
|
*
|
||||||
|
* Cancellation does not alter the set of registered signals.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @note If a registered signal occurred before cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous operation to wait for a signal to be delivered.
|
||||||
|
/**
|
||||||
|
* This function may be used to initiate an asynchronous wait against the
|
||||||
|
* signal set. It is an initiating function for an @ref
|
||||||
|
* asynchronous_operation, and always returns immediately.
|
||||||
|
*
|
||||||
|
* For each call to async_wait(), the completion handler will be called
|
||||||
|
* exactly once. The completion handler will be called when:
|
||||||
|
*
|
||||||
|
* @li One of the registered signals in the signal set occurs; or
|
||||||
|
*
|
||||||
|
* @li The signal set was cancelled, in which case the handler is passed the
|
||||||
|
* error code asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the wait completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* int signal_number // Indicates which signal occurred.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, int) @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* This asynchronous operation supports cancellation for the following
|
||||||
|
* asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, int))
|
||||||
|
SignalToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(SignalToken,
|
||||||
|
void (asio::error_code, int))
|
||||||
|
async_wait(
|
||||||
|
ASIO_MOVE_ARG(SignalToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<SignalToken, void (asio::error_code, int)>(
|
||||||
|
initiate_async_wait(this), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_signal_set(const basic_signal_set&) ASIO_DELETED;
|
||||||
|
basic_signal_set& operator=(const basic_signal_set&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_wait
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_wait(basic_signal_set* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SignalHandler>
|
||||||
|
void operator()(ASIO_MOVE_ARG(SignalHandler) handler) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a SignalHandler.
|
||||||
|
ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<SignalHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_wait(
|
||||||
|
self_->impl_.get_implementation(),
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_signal_set* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
detail::io_object_impl<detail::signal_set_service, Executor> impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_SIGNAL_SET_HPP
|
1936
lib/asio/include/asio/basic_socket.hpp
Normal file
1936
lib/asio/include/asio/basic_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
2686
lib/asio/include/asio/basic_socket_acceptor.hpp
Normal file
2686
lib/asio/include/asio/basic_socket_acceptor.hpp
Normal file
File diff suppressed because it is too large
Load Diff
407
lib/asio/include/asio/basic_socket_iostream.hpp
Normal file
407
lib/asio/include/asio/basic_socket_iostream.hpp
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
//
|
||||||
|
// basic_socket_iostream.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP
|
||||||
|
#define ASIO_BASIC_SOCKET_IOSTREAM_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
#include "asio/basic_socket_streambuf.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
# include "asio/detail/variadic_templates.hpp"
|
||||||
|
|
||||||
|
// A macro that should expand to:
|
||||||
|
// template <typename T1, ..., typename Tn>
|
||||||
|
// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
|
||||||
|
// : std::basic_iostream<char>(
|
||||||
|
// &this->detail::socket_iostream_base<
|
||||||
|
// Protocol, Clock, WaitTraits>::streambuf_)
|
||||||
|
// {
|
||||||
|
// if (rdbuf()->connect(x1, ..., xn) == 0)
|
||||||
|
// this->setstate(std::ios_base::failbit);
|
||||||
|
// }
|
||||||
|
// This macro should only persist within this file.
|
||||||
|
|
||||||
|
# define ASIO_PRIVATE_CTR_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
|
||||||
|
: std::basic_iostream<char>( \
|
||||||
|
&this->detail::socket_iostream_base< \
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_) \
|
||||||
|
{ \
|
||||||
|
this->setf(std::ios_base::unitbuf); \
|
||||||
|
if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
|
||||||
|
this->setstate(std::ios_base::failbit); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
// A macro that should expand to:
|
||||||
|
// template <typename T1, ..., typename Tn>
|
||||||
|
// void connect(T1 x1, ..., Tn xn)
|
||||||
|
// {
|
||||||
|
// if (rdbuf()->connect(x1, ..., xn) == 0)
|
||||||
|
// this->setstate(std::ios_base::failbit);
|
||||||
|
// }
|
||||||
|
// This macro should only persist within this file.
|
||||||
|
|
||||||
|
# define ASIO_PRIVATE_CONNECT_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
|
||||||
|
this->setstate(std::ios_base::failbit); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// A separate base class is used to ensure that the streambuf is initialised
|
||||||
|
// prior to the basic_socket_iostream's basic_iostream base class.
|
||||||
|
template <typename Protocol, typename Clock, typename WaitTraits>
|
||||||
|
class socket_iostream_base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
socket_iostream_base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
socket_iostream_base(socket_iostream_base&& other)
|
||||||
|
: streambuf_(std::move(other.streambuf_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_iostream_base(basic_stream_socket<Protocol> s)
|
||||||
|
: streambuf_(std::move(s))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_iostream_base& operator=(socket_iostream_base&& other)
|
||||||
|
{
|
||||||
|
streambuf_ = std::move(other.streambuf_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Protocol,
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typename Clock = boost::posix_time::ptime,
|
||||||
|
typename WaitTraits = time_traits<Clock> >
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typename Clock = chrono::steady_clock,
|
||||||
|
typename WaitTraits = wait_traits<Clock> >
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
class basic_socket_iostream;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
|
||||||
|
|
||||||
|
/// Iostream interface for a socket.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Protocol,
|
||||||
|
typename Clock = chrono::steady_clock,
|
||||||
|
typename WaitTraits = wait_traits<Clock> >
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Protocol, typename Clock, typename WaitTraits>
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
class basic_socket_iostream
|
||||||
|
: private detail::socket_iostream_base<Protocol, Clock, WaitTraits>,
|
||||||
|
public std::basic_iostream<char>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// These typedefs are intended keep this class's implementation independent
|
||||||
|
// of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typedef WaitTraits traits_helper;
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The protocol type.
|
||||||
|
typedef Protocol protocol_type;
|
||||||
|
|
||||||
|
/// The endpoint type.
|
||||||
|
typedef typename Protocol::endpoint endpoint_type;
|
||||||
|
|
||||||
|
/// The clock type.
|
||||||
|
typedef Clock clock_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// (Deprecated: Use time_point.) The time type.
|
||||||
|
typedef typename WaitTraits::time_type time_type;
|
||||||
|
|
||||||
|
/// The time type.
|
||||||
|
typedef typename WaitTraits::time_point time_point;
|
||||||
|
|
||||||
|
/// (Deprecated: Use duration.) The duration type.
|
||||||
|
typedef typename WaitTraits::duration_type duration_type;
|
||||||
|
|
||||||
|
/// The duration type.
|
||||||
|
typedef typename WaitTraits::duration duration;
|
||||||
|
#else
|
||||||
|
# if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
typedef typename traits_helper::time_type time_type;
|
||||||
|
typedef typename traits_helper::duration_type duration_type;
|
||||||
|
# endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
typedef typename traits_helper::time_type time_point;
|
||||||
|
typedef typename traits_helper::duration_type duration;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_socket_iostream without establishing a connection.
|
||||||
|
basic_socket_iostream()
|
||||||
|
: std::basic_iostream<char>(
|
||||||
|
&this->detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_)
|
||||||
|
{
|
||||||
|
this->setf(std::ios_base::unitbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Construct a basic_socket_iostream from the supplied socket.
|
||||||
|
explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
|
||||||
|
: detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>(std::move(s)),
|
||||||
|
std::basic_iostream<char>(
|
||||||
|
&this->detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_)
|
||||||
|
{
|
||||||
|
this->setf(std::ios_base::unitbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_IOSTREAM_MOVE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_socket_iostream from another.
|
||||||
|
basic_socket_iostream(basic_socket_iostream&& other)
|
||||||
|
: detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>(std::move(other)),
|
||||||
|
std::basic_iostream<char>(std::move(other))
|
||||||
|
{
|
||||||
|
this->set_rdbuf(&this->detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_socket_iostream from another.
|
||||||
|
basic_socket_iostream& operator=(basic_socket_iostream&& other)
|
||||||
|
{
|
||||||
|
std::basic_iostream<char>::operator=(std::move(other));
|
||||||
|
detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_STD_IOSTREAM_MOVE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Establish a connection to an endpoint corresponding to a resolver query.
|
||||||
|
/**
|
||||||
|
* This constructor automatically establishes a connection based on the
|
||||||
|
* supplied resolver query parameters. The arguments are used to construct
|
||||||
|
* a resolver query object.
|
||||||
|
*/
|
||||||
|
template <typename T1, ..., typename TN>
|
||||||
|
explicit basic_socket_iostream(T1 t1, ..., TN tn);
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
template <typename... T>
|
||||||
|
explicit basic_socket_iostream(T... x)
|
||||||
|
: std::basic_iostream<char>(
|
||||||
|
&this->detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_)
|
||||||
|
{
|
||||||
|
this->setf(std::ios_base::unitbuf);
|
||||||
|
if (rdbuf()->connect(x...) == 0)
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CTR_DEF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Establish a connection to an endpoint corresponding to a resolver query.
|
||||||
|
/**
|
||||||
|
* This function automatically establishes a connection based on the supplied
|
||||||
|
* resolver query parameters. The arguments are used to construct a resolver
|
||||||
|
* query object.
|
||||||
|
*/
|
||||||
|
template <typename T1, ..., typename TN>
|
||||||
|
void connect(T1 t1, ..., TN tn);
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
template <typename... T>
|
||||||
|
void connect(T... x)
|
||||||
|
{
|
||||||
|
if (rdbuf()->connect(x...) == 0)
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Close the connection.
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
if (rdbuf()->close() == 0)
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a pointer to the underlying streambuf.
|
||||||
|
basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const
|
||||||
|
{
|
||||||
|
return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(
|
||||||
|
&this->detail::socket_iostream_base<
|
||||||
|
Protocol, Clock, WaitTraits>::streambuf_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the underlying socket.
|
||||||
|
basic_socket<Protocol>& socket()
|
||||||
|
{
|
||||||
|
return rdbuf()->socket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the last error associated with the stream.
|
||||||
|
/**
|
||||||
|
* @return An \c error_code corresponding to the last error from the stream.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To print the error associated with a failure to establish a connection:
|
||||||
|
* @code tcp::iostream s("www.boost.org", "http");
|
||||||
|
* if (!s)
|
||||||
|
* {
|
||||||
|
* std::cout << "Error: " << s.error().message() << std::endl;
|
||||||
|
* } @endcode
|
||||||
|
*/
|
||||||
|
const asio::error_code& error() const
|
||||||
|
{
|
||||||
|
return rdbuf()->error();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use expiry().) Get the stream's expiry time as an absolute
|
||||||
|
/// time.
|
||||||
|
/**
|
||||||
|
* @return An absolute time value representing the stream's expiry time.
|
||||||
|
*/
|
||||||
|
time_point expires_at() const
|
||||||
|
{
|
||||||
|
return rdbuf()->expires_at();
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Get the stream's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* @return An absolute time value representing the stream's expiry time.
|
||||||
|
*/
|
||||||
|
time_point expiry() const
|
||||||
|
{
|
||||||
|
return rdbuf()->expiry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the stream's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the stream.
|
||||||
|
*/
|
||||||
|
void expires_at(const time_point& expiry_time)
|
||||||
|
{
|
||||||
|
rdbuf()->expires_at(expiry_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the stream's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*/
|
||||||
|
void expires_after(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
rdbuf()->expires_after(expiry_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use expiry().) Get the stream's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* @return A relative time value representing the stream's expiry time.
|
||||||
|
*/
|
||||||
|
duration expires_from_now() const
|
||||||
|
{
|
||||||
|
return rdbuf()->expires_from_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expires_after().) Set the stream's expiry time relative
|
||||||
|
/// to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*/
|
||||||
|
void expires_from_now(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
rdbuf()->expires_from_now(expiry_time);
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_socket_iostream(const basic_socket_iostream&) ASIO_DELETED;
|
||||||
|
basic_socket_iostream& operator=(
|
||||||
|
const basic_socket_iostream&) ASIO_DELETED;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
# undef ASIO_PRIVATE_CTR_DEF
|
||||||
|
# undef ASIO_PRIVATE_CONNECT_DEF
|
||||||
|
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP
|
687
lib/asio/include/asio/basic_socket_streambuf.hpp
Normal file
687
lib/asio/include/asio/basic_socket_streambuf.hpp
Normal file
@ -0,0 +1,687 @@
|
|||||||
|
//
|
||||||
|
// basic_socket_streambuf.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_SOCKET_STREAMBUF_HPP
|
||||||
|
#define ASIO_BASIC_SOCKET_STREAMBUF_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#include <streambuf>
|
||||||
|
#include <vector>
|
||||||
|
#include "asio/basic_socket.hpp"
|
||||||
|
#include "asio/basic_stream_socket.hpp"
|
||||||
|
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||||
|
#include "asio/detail/memory.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/io_context.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
# include "asio/detail/deadline_timer_service.hpp"
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
# include "asio/steady_timer.hpp"
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
# include "asio/detail/variadic_templates.hpp"
|
||||||
|
|
||||||
|
// A macro that should expand to:
|
||||||
|
// template <typename T1, ..., typename Tn>
|
||||||
|
// basic_socket_streambuf* connect(T1 x1, ..., Tn xn)
|
||||||
|
// {
|
||||||
|
// init_buffers();
|
||||||
|
// typedef typename Protocol::resolver resolver_type;
|
||||||
|
// resolver_type resolver(socket().get_executor());
|
||||||
|
// connect_to_endpoints(
|
||||||
|
// resolver.resolve(x1, ..., xn, ec_));
|
||||||
|
// return !ec_ ? this : 0;
|
||||||
|
// }
|
||||||
|
// This macro should only persist within this file.
|
||||||
|
|
||||||
|
# define ASIO_PRIVATE_CONNECT_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
basic_socket_streambuf* connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
init_buffers(); \
|
||||||
|
typedef typename Protocol::resolver resolver_type; \
|
||||||
|
resolver_type resolver(socket().get_executor()); \
|
||||||
|
connect_to_endpoints( \
|
||||||
|
resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
|
||||||
|
return !ec_ ? this : 0; \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// A separate base class is used to ensure that the io_context member is
|
||||||
|
// initialised prior to the basic_socket_streambuf's basic_socket base class.
|
||||||
|
class socket_streambuf_io_context
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
socket_streambuf_io_context(io_context* ctx)
|
||||||
|
: default_io_context_(ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<io_context> default_io_context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A separate base class is used to ensure that the dynamically allocated
|
||||||
|
// buffers are constructed prior to the basic_socket_streambuf's basic_socket
|
||||||
|
// base class. This makes moving the socket is the last potentially throwing
|
||||||
|
// step in the streambuf's move constructor, giving the constructor a strong
|
||||||
|
// exception safety guarantee.
|
||||||
|
class socket_streambuf_buffers
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
socket_streambuf_buffers()
|
||||||
|
: get_buffer_(buffer_size),
|
||||||
|
put_buffer_(buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { buffer_size = 512 };
|
||||||
|
std::vector<char> get_buffer_;
|
||||||
|
std::vector<char> put_buffer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Protocol,
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typename Clock = boost::posix_time::ptime,
|
||||||
|
typename WaitTraits = time_traits<Clock> >
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typename Clock = chrono::steady_clock,
|
||||||
|
typename WaitTraits = wait_traits<Clock> >
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
class basic_socket_streambuf;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
|
||||||
|
|
||||||
|
/// Iostream streambuf for a socket.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Protocol,
|
||||||
|
typename Clock = chrono::steady_clock,
|
||||||
|
typename WaitTraits = wait_traits<Clock> >
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Protocol, typename Clock, typename WaitTraits>
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
class basic_socket_streambuf
|
||||||
|
: public std::streambuf,
|
||||||
|
private detail::socket_streambuf_io_context,
|
||||||
|
private detail::socket_streambuf_buffers,
|
||||||
|
#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
private basic_socket<Protocol>
|
||||||
|
#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
public basic_socket<Protocol>
|
||||||
|
#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// These typedefs are intended keep this class's implementation independent
|
||||||
|
// of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typedef WaitTraits traits_helper;
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The protocol type.
|
||||||
|
typedef Protocol protocol_type;
|
||||||
|
|
||||||
|
/// The endpoint type.
|
||||||
|
typedef typename Protocol::endpoint endpoint_type;
|
||||||
|
|
||||||
|
/// The clock type.
|
||||||
|
typedef Clock clock_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// (Deprecated: Use time_point.) The time type.
|
||||||
|
typedef typename WaitTraits::time_type time_type;
|
||||||
|
|
||||||
|
/// The time type.
|
||||||
|
typedef typename WaitTraits::time_point time_point;
|
||||||
|
|
||||||
|
/// (Deprecated: Use duration.) The duration type.
|
||||||
|
typedef typename WaitTraits::duration_type duration_type;
|
||||||
|
|
||||||
|
/// The duration type.
|
||||||
|
typedef typename WaitTraits::duration duration;
|
||||||
|
#else
|
||||||
|
# if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
typedef typename traits_helper::time_type time_type;
|
||||||
|
typedef typename traits_helper::duration_type duration_type;
|
||||||
|
# endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
typedef typename traits_helper::time_type time_point;
|
||||||
|
typedef typename traits_helper::duration_type duration;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_socket_streambuf without establishing a connection.
|
||||||
|
basic_socket_streambuf()
|
||||||
|
: detail::socket_streambuf_io_context(new io_context),
|
||||||
|
basic_socket<Protocol>(*default_io_context_),
|
||||||
|
expiry_time_(max_expiry_time())
|
||||||
|
{
|
||||||
|
init_buffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Construct a basic_socket_streambuf from the supplied socket.
|
||||||
|
explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
|
||||||
|
: detail::socket_streambuf_io_context(0),
|
||||||
|
basic_socket<Protocol>(std::move(s)),
|
||||||
|
expiry_time_(max_expiry_time())
|
||||||
|
{
|
||||||
|
init_buffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-construct a basic_socket_streambuf from another.
|
||||||
|
basic_socket_streambuf(basic_socket_streambuf&& other)
|
||||||
|
: detail::socket_streambuf_io_context(other),
|
||||||
|
basic_socket<Protocol>(std::move(other.socket())),
|
||||||
|
ec_(other.ec_),
|
||||||
|
expiry_time_(other.expiry_time_)
|
||||||
|
{
|
||||||
|
get_buffer_.swap(other.get_buffer_);
|
||||||
|
put_buffer_.swap(other.put_buffer_);
|
||||||
|
setg(other.eback(), other.gptr(), other.egptr());
|
||||||
|
setp(other.pptr(), other.epptr());
|
||||||
|
other.ec_ = asio::error_code();
|
||||||
|
other.expiry_time_ = max_expiry_time();
|
||||||
|
other.init_buffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_socket_streambuf from another.
|
||||||
|
basic_socket_streambuf& operator=(basic_socket_streambuf&& other)
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
socket() = std::move(other.socket());
|
||||||
|
detail::socket_streambuf_io_context::operator=(other);
|
||||||
|
ec_ = other.ec_;
|
||||||
|
expiry_time_ = other.expiry_time_;
|
||||||
|
get_buffer_.swap(other.get_buffer_);
|
||||||
|
put_buffer_.swap(other.put_buffer_);
|
||||||
|
setg(other.eback(), other.gptr(), other.egptr());
|
||||||
|
setp(other.pptr(), other.epptr());
|
||||||
|
other.ec_ = asio::error_code();
|
||||||
|
other.expiry_time_ = max_expiry_time();
|
||||||
|
other.put_buffer_.resize(buffer_size);
|
||||||
|
other.init_buffers();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destructor flushes buffered data.
|
||||||
|
virtual ~basic_socket_streambuf()
|
||||||
|
{
|
||||||
|
if (pptr() != pbase())
|
||||||
|
overflow(traits_type::eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establish a connection.
|
||||||
|
/**
|
||||||
|
* This function establishes a connection to the specified endpoint.
|
||||||
|
*
|
||||||
|
* @return \c this if a connection was successfully established, a null
|
||||||
|
* pointer otherwise.
|
||||||
|
*/
|
||||||
|
basic_socket_streambuf* connect(const endpoint_type& endpoint)
|
||||||
|
{
|
||||||
|
init_buffers();
|
||||||
|
ec_ = asio::error_code();
|
||||||
|
this->connect_to_endpoints(&endpoint, &endpoint + 1);
|
||||||
|
return !ec_ ? this : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Establish a connection.
|
||||||
|
/**
|
||||||
|
* This function automatically establishes a connection based on the supplied
|
||||||
|
* resolver query parameters. The arguments are used to construct a resolver
|
||||||
|
* query object.
|
||||||
|
*
|
||||||
|
* @return \c this if a connection was successfully established, a null
|
||||||
|
* pointer otherwise.
|
||||||
|
*/
|
||||||
|
template <typename T1, ..., typename TN>
|
||||||
|
basic_socket_streambuf* connect(T1 t1, ..., TN tn);
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
template <typename... T>
|
||||||
|
basic_socket_streambuf* connect(T... x)
|
||||||
|
{
|
||||||
|
init_buffers();
|
||||||
|
typedef typename Protocol::resolver resolver_type;
|
||||||
|
resolver_type resolver(socket().get_executor());
|
||||||
|
connect_to_endpoints(resolver.resolve(x..., ec_));
|
||||||
|
return !ec_ ? this : 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Close the connection.
|
||||||
|
/**
|
||||||
|
* @return \c this if a connection was successfully established, a null
|
||||||
|
* pointer otherwise.
|
||||||
|
*/
|
||||||
|
basic_socket_streambuf* close()
|
||||||
|
{
|
||||||
|
sync();
|
||||||
|
socket().close(ec_);
|
||||||
|
if (!ec_)
|
||||||
|
init_buffers();
|
||||||
|
return !ec_ ? this : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the underlying socket.
|
||||||
|
basic_socket<Protocol>& socket()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the last error associated with the stream buffer.
|
||||||
|
/**
|
||||||
|
* @return An \c error_code corresponding to the last error from the stream
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
const asio::error_code& error() const
|
||||||
|
{
|
||||||
|
return ec_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use error().) Get the last error associated with the stream
|
||||||
|
/// buffer.
|
||||||
|
/**
|
||||||
|
* @return An \c error_code corresponding to the last error from the stream
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
const asio::error_code& puberror() const
|
||||||
|
{
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expiry().) Get the stream buffer's expiry time as an
|
||||||
|
/// absolute time.
|
||||||
|
/**
|
||||||
|
* @return An absolute time value representing the stream buffer's expiry
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
time_point expires_at() const
|
||||||
|
{
|
||||||
|
return expiry_time_;
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Get the stream buffer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* @return An absolute time value representing the stream buffer's expiry
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
time_point expiry() const
|
||||||
|
{
|
||||||
|
return expiry_time_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the stream buffer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the stream.
|
||||||
|
*/
|
||||||
|
void expires_at(const time_point& expiry_time)
|
||||||
|
{
|
||||||
|
expiry_time_ = expiry_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the stream buffer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*/
|
||||||
|
void expires_after(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use expiry().) Get the stream buffer's expiry time relative
|
||||||
|
/// to now.
|
||||||
|
/**
|
||||||
|
* @return A relative time value representing the stream buffer's expiry time.
|
||||||
|
*/
|
||||||
|
duration expires_from_now() const
|
||||||
|
{
|
||||||
|
return traits_helper::subtract(expires_at(), traits_helper::now());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expires_after().) Set the stream buffer's expiry time
|
||||||
|
/// relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time associated with the stream. Stream
|
||||||
|
* operations performed after this time (where the operations cannot be
|
||||||
|
* completed using the internal buffers) will fail with the error
|
||||||
|
* asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*/
|
||||||
|
void expires_from_now(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int_type underflow()
|
||||||
|
{
|
||||||
|
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
ec_ = asio::error::operation_not_supported;
|
||||||
|
return traits_type::eof();
|
||||||
|
#else // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
if (gptr() != egptr())
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Check if we are past the expiry time.
|
||||||
|
if (traits_helper::less_than(expiry_time_, traits_helper::now()))
|
||||||
|
{
|
||||||
|
ec_ = asio::error::timed_out;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to complete the operation without blocking.
|
||||||
|
if (!socket().native_non_blocking())
|
||||||
|
socket().native_non_blocking(true, ec_);
|
||||||
|
detail::buffer_sequence_adapter<mutable_buffer, mutable_buffer>
|
||||||
|
bufs(asio::buffer(get_buffer_) + putback_max);
|
||||||
|
detail::signed_size_type bytes = detail::socket_ops::recv(
|
||||||
|
socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
|
||||||
|
|
||||||
|
// Check if operation succeeded.
|
||||||
|
if (bytes > 0)
|
||||||
|
{
|
||||||
|
setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
|
||||||
|
&get_buffer_[0] + putback_max + bytes);
|
||||||
|
return traits_type::to_int_type(*gptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for EOF.
|
||||||
|
if (bytes == 0)
|
||||||
|
{
|
||||||
|
ec_ = asio::error::eof;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operation failed.
|
||||||
|
if (ec_ != asio::error::would_block
|
||||||
|
&& ec_ != asio::error::try_again)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
// Wait for socket to become ready.
|
||||||
|
if (detail::socket_ops::poll_read(
|
||||||
|
socket().native_handle(), 0, timeout(), ec_) < 0)
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
int_type overflow(int_type c)
|
||||||
|
{
|
||||||
|
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
ec_ = asio::error::operation_not_supported;
|
||||||
|
return traits_type::eof();
|
||||||
|
#else // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
char_type ch = traits_type::to_char_type(c);
|
||||||
|
|
||||||
|
// Determine what needs to be sent.
|
||||||
|
const_buffer output_buffer;
|
||||||
|
if (put_buffer_.empty())
|
||||||
|
{
|
||||||
|
if (traits_type::eq_int_type(c, traits_type::eof()))
|
||||||
|
return traits_type::not_eof(c); // Nothing to do.
|
||||||
|
output_buffer = asio::buffer(&ch, sizeof(char_type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_buffer = asio::buffer(pbase(),
|
||||||
|
(pptr() - pbase()) * sizeof(char_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (output_buffer.size() > 0)
|
||||||
|
{
|
||||||
|
// Check if we are past the expiry time.
|
||||||
|
if (traits_helper::less_than(expiry_time_, traits_helper::now()))
|
||||||
|
{
|
||||||
|
ec_ = asio::error::timed_out;
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to complete the operation without blocking.
|
||||||
|
if (!socket().native_non_blocking())
|
||||||
|
socket().native_non_blocking(true, ec_);
|
||||||
|
detail::buffer_sequence_adapter<
|
||||||
|
const_buffer, const_buffer> bufs(output_buffer);
|
||||||
|
detail::signed_size_type bytes = detail::socket_ops::send(
|
||||||
|
socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
|
||||||
|
|
||||||
|
// Check if operation succeeded.
|
||||||
|
if (bytes > 0)
|
||||||
|
{
|
||||||
|
output_buffer += static_cast<std::size_t>(bytes);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operation failed.
|
||||||
|
if (ec_ != asio::error::would_block
|
||||||
|
&& ec_ != asio::error::try_again)
|
||||||
|
return traits_type::eof();
|
||||||
|
|
||||||
|
// Wait for socket to become ready.
|
||||||
|
if (detail::socket_ops::poll_write(
|
||||||
|
socket().native_handle(), 0, timeout(), ec_) < 0)
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!put_buffer_.empty())
|
||||||
|
{
|
||||||
|
setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
|
||||||
|
|
||||||
|
// If the new character is eof then our work here is done.
|
||||||
|
if (traits_type::eq_int_type(c, traits_type::eof()))
|
||||||
|
return traits_type::not_eof(c);
|
||||||
|
|
||||||
|
// Add the new character to the output buffer.
|
||||||
|
*pptr() = ch;
|
||||||
|
pbump(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
#endif // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync()
|
||||||
|
{
|
||||||
|
return overflow(traits_type::eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streambuf* setbuf(char_type* s, std::streamsize n)
|
||||||
|
{
|
||||||
|
if (pptr() == pbase() && s == 0 && n == 0)
|
||||||
|
{
|
||||||
|
put_buffer_.clear();
|
||||||
|
setp(0, 0);
|
||||||
|
sync();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_socket_streambuf(const basic_socket_streambuf&) ASIO_DELETED;
|
||||||
|
basic_socket_streambuf& operator=(
|
||||||
|
const basic_socket_streambuf&) ASIO_DELETED;
|
||||||
|
|
||||||
|
void init_buffers()
|
||||||
|
{
|
||||||
|
setg(&get_buffer_[0],
|
||||||
|
&get_buffer_[0] + putback_max,
|
||||||
|
&get_buffer_[0] + putback_max);
|
||||||
|
|
||||||
|
if (put_buffer_.empty())
|
||||||
|
setp(0, 0);
|
||||||
|
else
|
||||||
|
setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout() const
|
||||||
|
{
|
||||||
|
int64_t msec = traits_helper::to_posix_duration(
|
||||||
|
traits_helper::subtract(expiry_time_,
|
||||||
|
traits_helper::now())).total_milliseconds();
|
||||||
|
if (msec > (std::numeric_limits<int>::max)())
|
||||||
|
msec = (std::numeric_limits<int>::max)();
|
||||||
|
else if (msec < 0)
|
||||||
|
msec = 0;
|
||||||
|
return static_cast<int>(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EndpointSequence>
|
||||||
|
void connect_to_endpoints(const EndpointSequence& endpoints)
|
||||||
|
{
|
||||||
|
this->connect_to_endpoints(endpoints.begin(), endpoints.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EndpointIterator>
|
||||||
|
void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
|
||||||
|
{
|
||||||
|
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
ec_ = asio::error::operation_not_supported;
|
||||||
|
#else // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
if (ec_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ec_ = asio::error::not_found;
|
||||||
|
for (EndpointIterator i = begin; i != end; ++i)
|
||||||
|
{
|
||||||
|
// Check if we are past the expiry time.
|
||||||
|
if (traits_helper::less_than(expiry_time_, traits_helper::now()))
|
||||||
|
{
|
||||||
|
ec_ = asio::error::timed_out;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close and reopen the socket.
|
||||||
|
typename Protocol::endpoint ep(*i);
|
||||||
|
socket().close(ec_);
|
||||||
|
socket().open(ep.protocol(), ec_);
|
||||||
|
if (ec_)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Try to complete the operation without blocking.
|
||||||
|
if (!socket().native_non_blocking())
|
||||||
|
socket().native_non_blocking(true, ec_);
|
||||||
|
detail::socket_ops::connect(socket().native_handle(),
|
||||||
|
ep.data(), ep.size(), ec_);
|
||||||
|
|
||||||
|
// Check if operation succeeded.
|
||||||
|
if (!ec_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Operation failed.
|
||||||
|
if (ec_ != asio::error::in_progress
|
||||||
|
&& ec_ != asio::error::would_block)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Wait for socket to become ready.
|
||||||
|
if (detail::socket_ops::poll_connect(
|
||||||
|
socket().native_handle(), timeout(), ec_) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the error code from the connect operation.
|
||||||
|
int connect_error = 0;
|
||||||
|
size_t connect_error_len = sizeof(connect_error);
|
||||||
|
if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
|
||||||
|
SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
|
||||||
|
== detail::socket_error_retval)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check the result of the connect operation.
|
||||||
|
ec_ = asio::error_code(connect_error,
|
||||||
|
asio::error::get_system_category());
|
||||||
|
if (!ec_)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_WINDOWS_RUNTIME)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get the maximum expiry time.
|
||||||
|
static time_point max_expiry_time()
|
||||||
|
{
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
&& defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
return boost::posix_time::pos_infin;
|
||||||
|
#else // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
return (time_point::max)();
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { putback_max = 8 };
|
||||||
|
asio::error_code ec_;
|
||||||
|
time_point expiry_time_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
# undef ASIO_PRIVATE_CONNECT_DEF
|
||||||
|
#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP
|
742
lib/asio/include/asio/basic_stream_file.hpp
Normal file
742
lib/asio/include/asio/basic_stream_file.hpp
Normal file
@ -0,0 +1,742 @@
|
|||||||
|
//
|
||||||
|
// basic_stream_file.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_STREAM_FILE_HPP
|
||||||
|
#define ASIO_BASIC_STREAM_FILE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_FILE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/basic_file.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_STREAM_FILE_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_stream_file;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)
|
||||||
|
|
||||||
|
/// Provides stream-oriented file functionality.
|
||||||
|
/**
|
||||||
|
* The basic_stream_file class template provides asynchronous and blocking
|
||||||
|
* stream-oriented file functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Concepts:
|
||||||
|
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||||
|
*/
|
||||||
|
template <typename Executor>
|
||||||
|
class basic_stream_file
|
||||||
|
: public basic_file<Executor>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the file type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The file type when rebound to the specified executor.
|
||||||
|
typedef basic_stream_file<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a file.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef typename basic_file<Executor>::native_handle_type native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_stream_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it. The file needs to
|
||||||
|
* be opened before data can be read from or or written to it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*/
|
||||||
|
explicit basic_stream_file(const executor_type& ex)
|
||||||
|
: basic_file<Executor>(ex)
|
||||||
|
{
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_stream_file without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a file without opening it. The file needs to
|
||||||
|
* be opened before data can be read from or or written to it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_stream_file(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context)
|
||||||
|
{
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_stream_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_stream_file(const executor_type& ex,
|
||||||
|
const char* path, file_base::flags open_flags)
|
||||||
|
: basic_file<Executor>(ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
this->impl_.get_service().open(
|
||||||
|
this->impl_.get_implementation(),
|
||||||
|
path, open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_stream_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_stream_file(ExecutionContext& context,
|
||||||
|
const char* path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
this->impl_.get_service().open(
|
||||||
|
this->impl_.get_implementation(),
|
||||||
|
path, open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_stream_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_stream_file(const executor_type& ex,
|
||||||
|
const std::string& path, file_base::flags open_flags)
|
||||||
|
: basic_file<Executor>(ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
this->impl_.get_service().open(
|
||||||
|
this->impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and open a basic_stream_file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises and opens a file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param path The path name identifying the file to be opened.
|
||||||
|
*
|
||||||
|
* @param open_flags A set of flags that determine how the file should be
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_stream_file(ExecutionContext& context,
|
||||||
|
const std::string& path, file_base::flags open_flags,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
this->impl_.get_service().open(
|
||||||
|
this->impl_.get_implementation(),
|
||||||
|
path.c_str(), open_flags, ec);
|
||||||
|
asio::detail::throw_error(ec, "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_stream_file on an existing native file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a stream file object to hold an existing
|
||||||
|
* native file.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the file will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file The new underlying file implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_stream_file(const executor_type& ex,
|
||||||
|
const native_handle_type& native_file)
|
||||||
|
: basic_file<Executor>(ex, native_file)
|
||||||
|
{
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_stream_file on an existing native file.
|
||||||
|
/**
|
||||||
|
* This constructor initialises a stream file object to hold an existing
|
||||||
|
* native file.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the file will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the file.
|
||||||
|
*
|
||||||
|
* @param native_file The new underlying file implementation.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_stream_file(ExecutionContext& context,
|
||||||
|
const native_handle_type& native_file,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(context, native_file)
|
||||||
|
{
|
||||||
|
this->impl_.get_service().set_is_stream(
|
||||||
|
this->impl_.get_implementation(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_stream_file from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a stream file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_stream_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_stream_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_stream_file(basic_stream_file&& other) ASIO_NOEXCEPT
|
||||||
|
: basic_file<Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_stream_file from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a stream file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_stream_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_stream_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_stream_file& operator=(basic_stream_file&& other)
|
||||||
|
{
|
||||||
|
basic_file<Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-construct a basic_stream_file from a file of another executor
|
||||||
|
/// type.
|
||||||
|
/**
|
||||||
|
* This constructor moves a stream file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_stream_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_stream_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
basic_stream_file(basic_stream_file<Executor1>&& other,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: basic_file<Executor>(std::move(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_stream_file from a file of another executor type.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a stream file from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_stream_file object from which the move
|
||||||
|
* will occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_stream_file(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
basic_stream_file&
|
||||||
|
>::type operator=(basic_stream_file<Executor1>&& other)
|
||||||
|
{
|
||||||
|
basic_file<Executor>::operator=(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the file.
|
||||||
|
/**
|
||||||
|
* This function destroys the file, cancelling any outstanding asynchronous
|
||||||
|
* operations associated with the file as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_stream_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seek to a position in the file.
|
||||||
|
/**
|
||||||
|
* This function updates the current position in the file.
|
||||||
|
*
|
||||||
|
* @param offset The requested position in the file, relative to @c whence.
|
||||||
|
*
|
||||||
|
* @param whence One of @c seek_set, @c seek_cur or @c seek_end.
|
||||||
|
*
|
||||||
|
* @returns The new position relative to the beginning of the file.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
uint64_t seek(int64_t offset, file_base::seek_basis whence)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
uint64_t n = this->impl_.get_service().seek(
|
||||||
|
this->impl_.get_implementation(), offset, whence, ec);
|
||||||
|
asio::detail::throw_error(ec, "seek");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seek to a position in the file.
|
||||||
|
/**
|
||||||
|
* This function updates the current position in the file.
|
||||||
|
*
|
||||||
|
* @param offset The requested position in the file, relative to @c whence.
|
||||||
|
*
|
||||||
|
* @param whence One of @c seek_set, @c seek_cur or @c seek_end.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The new position relative to the beginning of the file.
|
||||||
|
*/
|
||||||
|
uint64_t seek(int64_t offset, file_base::seek_basis whence,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().seek(
|
||||||
|
this->impl_.get_implementation(), offset, whence, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the file.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the stream file. The function call
|
||||||
|
* will block until one or more bytes of the data has been written
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the file.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the end of the file was reached.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* file.write_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().write_some(
|
||||||
|
this->impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "write_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the file.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the stream file. The function call
|
||||||
|
* will block until one or more bytes of the data has been written
|
||||||
|
* successfully, or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the file.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().write_some(
|
||||||
|
this->impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously write data to the stream file.
|
||||||
|
* It is an initiating function for an @ref asynchronous_operation, and always
|
||||||
|
* returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the file.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the write completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes written.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The write operation may not transmit all of the data to the peer.
|
||||||
|
* Consider using the @ref async_write function if you need to ensure that all
|
||||||
|
* data is written before the asynchronous operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* file.async_write_some(asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WriteToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_write_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the file.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the stream file. The function
|
||||||
|
* call will block until one or more bytes of data has been read successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the end of the file was reached.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* file.read_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = this->impl_.get_service().read_some(
|
||||||
|
this->impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "read_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the file.
|
||||||
|
/**
|
||||||
|
* This function is used to read data from the stream file. The function
|
||||||
|
* call will block until one or more bytes of data has been read successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The read_some operation may not read all of the requested number of
|
||||||
|
* bytes. Consider using the @ref read function if you need to ensure that
|
||||||
|
* the requested amount of data is read before the blocking operation
|
||||||
|
* completes.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return this->impl_.get_service().read_some(
|
||||||
|
this->impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously read data from the stream file.
|
||||||
|
* It is an initiating function for an @ref asynchronous_operation, and always
|
||||||
|
* returns immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more buffers into which the data will be read.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the read completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes read.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The read operation may not read all of the requested number of bytes.
|
||||||
|
* Consider using the @ref async_read function if you need to ensure that the
|
||||||
|
* requested amount of data is read before the asynchronous operation
|
||||||
|
* completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To read into a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* file.async_read_some(asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on reading into multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* On POSIX or Windows operating systems, this asynchronous operation supports
|
||||||
|
* cancellation for the following asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<ReadToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_read_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_stream_file(const basic_stream_file&) ASIO_DELETED;
|
||||||
|
basic_stream_file& operator=(const basic_stream_file&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_write_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_write_some(basic_stream_file* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WriteHandler, typename ConstBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
|
||||||
|
const ConstBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WriteHandler.
|
||||||
|
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_write_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_stream_file* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class initiate_async_read_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_read_some(basic_stream_file* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReadHandler, typename MutableBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
|
||||||
|
const MutableBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a ReadHandler.
|
||||||
|
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_read_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_stream_file* self_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_FILE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_STREAM_FILE_HPP
|
1156
lib/asio/include/asio/basic_stream_socket.hpp
Normal file
1156
lib/asio/include/asio/basic_stream_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
452
lib/asio/include/asio/basic_streambuf.hpp
Normal file
452
lib/asio/include/asio/basic_streambuf.hpp
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
//
|
||||||
|
// basic_streambuf.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_STREAMBUF_HPP
|
||||||
|
#define ASIO_BASIC_STREAMBUF_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <vector>
|
||||||
|
#include "asio/basic_streambuf_fwd.hpp"
|
||||||
|
#include "asio/buffer.hpp"
|
||||||
|
#include "asio/detail/limits.hpp"
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/detail/throw_exception.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Automatically resizable buffer class based on std::streambuf.
|
||||||
|
/**
|
||||||
|
* The @c basic_streambuf class is derived from @c std::streambuf to associate
|
||||||
|
* the streambuf's input and output sequences with one or more character
|
||||||
|
* arrays. These character arrays are internal to the @c basic_streambuf
|
||||||
|
* object, but direct access to the array elements is provided to permit them
|
||||||
|
* to be used efficiently with I/O operations. Characters written to the output
|
||||||
|
* sequence of a @c basic_streambuf object are appended to the input sequence
|
||||||
|
* of the same object.
|
||||||
|
*
|
||||||
|
* The @c basic_streambuf class's public interface is intended to permit the
|
||||||
|
* following implementation strategies:
|
||||||
|
*
|
||||||
|
* @li A single contiguous character array, which is reallocated as necessary
|
||||||
|
* to accommodate changes in the size of the character sequence. This is the
|
||||||
|
* implementation approach currently used in Asio.
|
||||||
|
*
|
||||||
|
* @li A sequence of one or more character arrays, where each array is of the
|
||||||
|
* same size. Additional character array objects are appended to the sequence
|
||||||
|
* to accommodate changes in the size of the character sequence.
|
||||||
|
*
|
||||||
|
* @li A sequence of one or more character arrays of varying sizes. Additional
|
||||||
|
* character array objects are appended to the sequence to accommodate changes
|
||||||
|
* in the size of the character sequence.
|
||||||
|
*
|
||||||
|
* The constructor for basic_streambuf accepts a @c size_t argument specifying
|
||||||
|
* the maximum of the sum of the sizes of the input sequence and output
|
||||||
|
* sequence. During the lifetime of the @c basic_streambuf object, the following
|
||||||
|
* invariant holds:
|
||||||
|
* @code size() <= max_size()@endcode
|
||||||
|
* Any member function that would, if successful, cause the invariant to be
|
||||||
|
* violated shall throw an exception of class @c std::length_error.
|
||||||
|
*
|
||||||
|
* The constructor for @c basic_streambuf takes an Allocator argument. A copy
|
||||||
|
* of this argument is used for any memory allocation performed, by the
|
||||||
|
* constructor and by all member functions, during the lifetime of each @c
|
||||||
|
* basic_streambuf object.
|
||||||
|
*
|
||||||
|
* @par Examples
|
||||||
|
* Writing directly from an streambuf to a socket:
|
||||||
|
* @code
|
||||||
|
* asio::streambuf b;
|
||||||
|
* std::ostream os(&b);
|
||||||
|
* os << "Hello, World!\n";
|
||||||
|
*
|
||||||
|
* // try sending some data in input sequence
|
||||||
|
* size_t n = sock.send(b.data());
|
||||||
|
*
|
||||||
|
* b.consume(n); // sent data is removed from input sequence
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Reading from a socket directly into a streambuf:
|
||||||
|
* @code
|
||||||
|
* asio::streambuf b;
|
||||||
|
*
|
||||||
|
* // reserve 512 bytes in output sequence
|
||||||
|
* asio::streambuf::mutable_buffers_type bufs = b.prepare(512);
|
||||||
|
*
|
||||||
|
* size_t n = sock.receive(bufs);
|
||||||
|
*
|
||||||
|
* // received data is "committed" from output sequence to input sequence
|
||||||
|
* b.commit(n);
|
||||||
|
*
|
||||||
|
* std::istream is(&b);
|
||||||
|
* std::string s;
|
||||||
|
* is >> s;
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Allocator = std::allocator<char> >
|
||||||
|
#else
|
||||||
|
template <typename Allocator>
|
||||||
|
#endif
|
||||||
|
class basic_streambuf
|
||||||
|
: public std::streambuf,
|
||||||
|
private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The type used to represent the input sequence as a list of buffers.
|
||||||
|
typedef implementation_defined const_buffers_type;
|
||||||
|
|
||||||
|
/// The type used to represent the output sequence as a list of buffers.
|
||||||
|
typedef implementation_defined mutable_buffers_type;
|
||||||
|
#else
|
||||||
|
typedef ASIO_CONST_BUFFER const_buffers_type;
|
||||||
|
typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct a basic_streambuf object.
|
||||||
|
/**
|
||||||
|
* Constructs a streambuf with the specified maximum size. The initial size
|
||||||
|
* of the streambuf's input sequence is 0.
|
||||||
|
*/
|
||||||
|
explicit basic_streambuf(
|
||||||
|
std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)(),
|
||||||
|
const Allocator& allocator = Allocator())
|
||||||
|
: max_size_(maximum_size),
|
||||||
|
buffer_(allocator)
|
||||||
|
{
|
||||||
|
std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
|
||||||
|
buffer_.resize((std::max<std::size_t>)(pend, 1));
|
||||||
|
setg(&buffer_[0], &buffer_[0], &buffer_[0]);
|
||||||
|
setp(&buffer_[0], &buffer_[0] + pend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the size of the input sequence.
|
||||||
|
/**
|
||||||
|
* @returns The size of the input sequence. The value is equal to that
|
||||||
|
* calculated for @c s in the following code:
|
||||||
|
* @code
|
||||||
|
* size_t s = 0;
|
||||||
|
* const_buffers_type bufs = data();
|
||||||
|
* const_buffers_type::const_iterator i = bufs.begin();
|
||||||
|
* while (i != bufs.end())
|
||||||
|
* {
|
||||||
|
* const_buffer buf(*i++);
|
||||||
|
* s += buf.size();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
std::size_t size() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return pptr() - gptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the maximum size of the basic_streambuf.
|
||||||
|
/**
|
||||||
|
* @returns The allowed maximum of the sum of the sizes of the input sequence
|
||||||
|
* and output sequence.
|
||||||
|
*/
|
||||||
|
std::size_t max_size() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return max_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current capacity of the basic_streambuf.
|
||||||
|
/**
|
||||||
|
* @returns The current total capacity of the streambuf, i.e. for both the
|
||||||
|
* input sequence and output sequence.
|
||||||
|
*/
|
||||||
|
std::size_t capacity() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffer_.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of buffers that represents the input sequence.
|
||||||
|
/**
|
||||||
|
* @returns An object of type @c const_buffers_type that satisfies
|
||||||
|
* ConstBufferSequence requirements, representing all character arrays in the
|
||||||
|
* input sequence.
|
||||||
|
*
|
||||||
|
* @note The returned object is invalidated by any @c basic_streambuf member
|
||||||
|
* function that modifies the input sequence or output sequence.
|
||||||
|
*/
|
||||||
|
const_buffers_type data() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return asio::buffer(asio::const_buffer(gptr(),
|
||||||
|
(pptr() - gptr()) * sizeof(char_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of buffers that represents the output sequence, with the given
|
||||||
|
/// size.
|
||||||
|
/**
|
||||||
|
* Ensures that the output sequence can accommodate @c n characters,
|
||||||
|
* reallocating character array objects as necessary.
|
||||||
|
*
|
||||||
|
* @returns An object of type @c mutable_buffers_type that satisfies
|
||||||
|
* MutableBufferSequence requirements, representing character array objects
|
||||||
|
* at the start of the output sequence such that the sum of the buffer sizes
|
||||||
|
* is @c n.
|
||||||
|
*
|
||||||
|
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
|
||||||
|
*
|
||||||
|
* @note The returned object is invalidated by any @c basic_streambuf member
|
||||||
|
* function that modifies the input sequence or output sequence.
|
||||||
|
*/
|
||||||
|
mutable_buffers_type prepare(std::size_t n)
|
||||||
|
{
|
||||||
|
reserve(n);
|
||||||
|
return asio::buffer(asio::mutable_buffer(
|
||||||
|
pptr(), n * sizeof(char_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move characters from the output sequence to the input sequence.
|
||||||
|
/**
|
||||||
|
* Appends @c n characters from the start of the output sequence to the input
|
||||||
|
* sequence. The beginning of the output sequence is advanced by @c n
|
||||||
|
* characters.
|
||||||
|
*
|
||||||
|
* Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
|
||||||
|
* no intervening operations that modify the input or output sequence.
|
||||||
|
*
|
||||||
|
* @note If @c n is greater than the size of the output sequence, the entire
|
||||||
|
* output sequence is moved to the input sequence and no error is issued.
|
||||||
|
*/
|
||||||
|
void commit(std::size_t n)
|
||||||
|
{
|
||||||
|
n = std::min<std::size_t>(n, epptr() - pptr());
|
||||||
|
pbump(static_cast<int>(n));
|
||||||
|
setg(eback(), gptr(), pptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove characters from the input sequence.
|
||||||
|
/**
|
||||||
|
* Removes @c n characters from the beginning of the input sequence.
|
||||||
|
*
|
||||||
|
* @note If @c n is greater than the size of the input sequence, the entire
|
||||||
|
* input sequence is consumed and no error is issued.
|
||||||
|
*/
|
||||||
|
void consume(std::size_t n)
|
||||||
|
{
|
||||||
|
if (egptr() < pptr())
|
||||||
|
setg(&buffer_[0], gptr(), pptr());
|
||||||
|
if (gptr() + n > pptr())
|
||||||
|
n = pptr() - gptr();
|
||||||
|
gbump(static_cast<int>(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum { buffer_delta = 128 };
|
||||||
|
|
||||||
|
/// Override std::streambuf behaviour.
|
||||||
|
/**
|
||||||
|
* Behaves according to the specification of @c std::streambuf::underflow().
|
||||||
|
*/
|
||||||
|
int_type underflow()
|
||||||
|
{
|
||||||
|
if (gptr() < pptr())
|
||||||
|
{
|
||||||
|
setg(&buffer_[0], gptr(), pptr());
|
||||||
|
return traits_type::to_int_type(*gptr());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Override std::streambuf behaviour.
|
||||||
|
/**
|
||||||
|
* Behaves according to the specification of @c std::streambuf::overflow(),
|
||||||
|
* with the specialisation that @c std::length_error is thrown if appending
|
||||||
|
* the character to the input sequence would require the condition
|
||||||
|
* <tt>size() > max_size()</tt> to be true.
|
||||||
|
*/
|
||||||
|
int_type overflow(int_type c)
|
||||||
|
{
|
||||||
|
if (!traits_type::eq_int_type(c, traits_type::eof()))
|
||||||
|
{
|
||||||
|
if (pptr() == epptr())
|
||||||
|
{
|
||||||
|
std::size_t buffer_size = pptr() - gptr();
|
||||||
|
if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
|
||||||
|
{
|
||||||
|
reserve(max_size_ - buffer_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reserve(buffer_delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pptr() = traits_type::to_char_type(c);
|
||||||
|
pbump(1);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return traits_type::not_eof(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(std::size_t n)
|
||||||
|
{
|
||||||
|
// Get current stream positions as offsets.
|
||||||
|
std::size_t gnext = gptr() - &buffer_[0];
|
||||||
|
std::size_t pnext = pptr() - &buffer_[0];
|
||||||
|
std::size_t pend = epptr() - &buffer_[0];
|
||||||
|
|
||||||
|
// Check if there is already enough space in the put area.
|
||||||
|
if (n <= pend - pnext)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift existing contents of get area to start of buffer.
|
||||||
|
if (gnext > 0)
|
||||||
|
{
|
||||||
|
pnext -= gnext;
|
||||||
|
std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure buffer is large enough to hold at least the specified size.
|
||||||
|
if (n > pend - pnext)
|
||||||
|
{
|
||||||
|
if (n <= max_size_ && pnext <= max_size_ - n)
|
||||||
|
{
|
||||||
|
pend = pnext + n;
|
||||||
|
buffer_.resize((std::max<std::size_t>)(pend, 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::length_error ex("asio::streambuf too long");
|
||||||
|
asio::detail::throw_exception(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update stream positions.
|
||||||
|
setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext);
|
||||||
|
setp(&buffer_[0] + pnext, &buffer_[0] + pend);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t max_size_;
|
||||||
|
std::vector<char_type, Allocator> buffer_;
|
||||||
|
|
||||||
|
// Helper function to get the preferred size for reading data.
|
||||||
|
friend std::size_t read_size_helper(
|
||||||
|
basic_streambuf& sb, std::size_t max_size)
|
||||||
|
{
|
||||||
|
return std::min<std::size_t>(
|
||||||
|
std::max<std::size_t>(512, sb.buffer_.capacity() - sb.size()),
|
||||||
|
std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Adapts basic_streambuf to the dynamic buffer sequence type requirements.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename Allocator = std::allocator<char> >
|
||||||
|
#else
|
||||||
|
template <typename Allocator>
|
||||||
|
#endif
|
||||||
|
class basic_streambuf_ref
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type used to represent the input sequence as a list of buffers.
|
||||||
|
typedef typename basic_streambuf<Allocator>::const_buffers_type
|
||||||
|
const_buffers_type;
|
||||||
|
|
||||||
|
/// The type used to represent the output sequence as a list of buffers.
|
||||||
|
typedef typename basic_streambuf<Allocator>::mutable_buffers_type
|
||||||
|
mutable_buffers_type;
|
||||||
|
|
||||||
|
/// Construct a basic_streambuf_ref for the given basic_streambuf object.
|
||||||
|
explicit basic_streambuf_ref(basic_streambuf<Allocator>& sb)
|
||||||
|
: sb_(sb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy construct a basic_streambuf_ref.
|
||||||
|
basic_streambuf_ref(const basic_streambuf_ref& other) ASIO_NOEXCEPT
|
||||||
|
: sb_(other.sb_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move construct a basic_streambuf_ref.
|
||||||
|
basic_streambuf_ref(basic_streambuf_ref&& other) ASIO_NOEXCEPT
|
||||||
|
: sb_(other.sb_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Get the size of the input sequence.
|
||||||
|
std::size_t size() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return sb_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the maximum size of the dynamic buffer.
|
||||||
|
std::size_t max_size() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return sb_.max_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current capacity of the dynamic buffer.
|
||||||
|
std::size_t capacity() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return sb_.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of buffers that represents the input sequence.
|
||||||
|
const_buffers_type data() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return sb_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of buffers that represents the output sequence, with the given
|
||||||
|
/// size.
|
||||||
|
mutable_buffers_type prepare(std::size_t n)
|
||||||
|
{
|
||||||
|
return sb_.prepare(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move bytes from the output sequence to the input sequence.
|
||||||
|
void commit(std::size_t n)
|
||||||
|
{
|
||||||
|
return sb_.commit(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove characters from the input sequence.
|
||||||
|
void consume(std::size_t n)
|
||||||
|
{
|
||||||
|
return sb_.consume(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_streambuf<Allocator>& sb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_STREAMBUF_HPP
|
36
lib/asio/include/asio/basic_streambuf_fwd.hpp
Normal file
36
lib/asio/include/asio/basic_streambuf_fwd.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// basic_streambuf_fwd.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_STREAMBUF_FWD_HPP
|
||||||
|
#define ASIO_BASIC_STREAMBUF_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename Allocator = std::allocator<char> >
|
||||||
|
class basic_streambuf;
|
||||||
|
|
||||||
|
template <typename Allocator = std::allocator<char> >
|
||||||
|
class basic_streambuf_ref;
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_NO_IOSTREAM)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_STREAMBUF_FWD_HPP
|
827
lib/asio/include/asio/basic_waitable_timer.hpp
Normal file
827
lib/asio/include/asio/basic_waitable_timer.hpp
Normal file
@ -0,0 +1,827 @@
|
|||||||
|
//
|
||||||
|
// basic_waitable_timer.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_WAITABLE_TIMER_HPP
|
||||||
|
#define ASIO_BASIC_WAITABLE_TIMER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/detail/chrono_time_traits.hpp"
|
||||||
|
#include "asio/detail/deadline_timer_service.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/wait_traits.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
|
||||||
|
#define ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
|
||||||
|
|
||||||
|
// Forward declaration with defaulted arguments.
|
||||||
|
template <typename Clock,
|
||||||
|
typename WaitTraits = asio::wait_traits<Clock>,
|
||||||
|
typename Executor = any_io_executor>
|
||||||
|
class basic_waitable_timer;
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
|
||||||
|
|
||||||
|
/// Provides waitable timer functionality.
|
||||||
|
/**
|
||||||
|
* The basic_waitable_timer class template provides the ability to perform a
|
||||||
|
* blocking or asynchronous wait for a timer to expire.
|
||||||
|
*
|
||||||
|
* A waitable timer is always in one of two states: "expired" or "not expired".
|
||||||
|
* If the wait() or async_wait() function is called on an expired timer, the
|
||||||
|
* wait operation will complete immediately.
|
||||||
|
*
|
||||||
|
* Most applications will use one of the asio::steady_timer,
|
||||||
|
* asio::system_timer or asio::high_resolution_timer typedefs.
|
||||||
|
*
|
||||||
|
* @note This waitable timer functionality is for use with the C++11 standard
|
||||||
|
* library's @c <chrono> facility, or with the Boost.Chrono library.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Examples
|
||||||
|
* Performing a blocking wait (C++11):
|
||||||
|
* @code
|
||||||
|
* // Construct a timer without setting an expiry time.
|
||||||
|
* asio::steady_timer timer(my_context);
|
||||||
|
*
|
||||||
|
* // Set an expiry time relative to now.
|
||||||
|
* timer.expires_after(std::chrono::seconds(5));
|
||||||
|
*
|
||||||
|
* // Wait for the timer to expire.
|
||||||
|
* timer.wait();
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par
|
||||||
|
* Performing an asynchronous wait (C++11):
|
||||||
|
* @code
|
||||||
|
* void handler(const asio::error_code& error)
|
||||||
|
* {
|
||||||
|
* if (!error)
|
||||||
|
* {
|
||||||
|
* // Timer expired.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* // Construct a timer with an absolute expiry time.
|
||||||
|
* asio::steady_timer timer(my_context,
|
||||||
|
* std::chrono::steady_clock::now() + std::chrono::seconds(60));
|
||||||
|
*
|
||||||
|
* // Start an asynchronous wait.
|
||||||
|
* timer.async_wait(handler);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Changing an active waitable timer's expiry time
|
||||||
|
*
|
||||||
|
* Changing the expiry time of a timer while there are pending asynchronous
|
||||||
|
* waits causes those wait operations to be cancelled. To ensure that the action
|
||||||
|
* associated with the timer is performed only once, use something like this:
|
||||||
|
* used:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* void on_some_event()
|
||||||
|
* {
|
||||||
|
* if (my_timer.expires_after(seconds(5)) > 0)
|
||||||
|
* {
|
||||||
|
* // We managed to cancel the timer. Start new asynchronous wait.
|
||||||
|
* my_timer.async_wait(on_timeout);
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Too late, timer has already expired!
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void on_timeout(const asio::error_code& e)
|
||||||
|
* {
|
||||||
|
* if (e != asio::error::operation_aborted)
|
||||||
|
* {
|
||||||
|
* // Timer was not cancelled, take necessary action.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @li The asio::basic_waitable_timer::expires_after() function
|
||||||
|
* cancels any pending asynchronous waits, and returns the number of
|
||||||
|
* asynchronous waits that were cancelled. If it returns 0 then you were too
|
||||||
|
* late and the wait handler has already been executed, or will soon be
|
||||||
|
* executed. If it returns 1 then the wait handler was successfully cancelled.
|
||||||
|
*
|
||||||
|
* @li If a wait handler is cancelled, the asio::error_code passed to
|
||||||
|
* it contains the value asio::error::operation_aborted.
|
||||||
|
*/
|
||||||
|
template <typename Clock, typename WaitTraits, typename Executor>
|
||||||
|
class basic_waitable_timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the timer type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The timer type when rebound to the specified executor.
|
||||||
|
typedef basic_waitable_timer<Clock, WaitTraits, Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The clock type.
|
||||||
|
typedef Clock clock_type;
|
||||||
|
|
||||||
|
/// The duration type of the clock.
|
||||||
|
typedef typename clock_type::duration duration;
|
||||||
|
|
||||||
|
/// The time point type of the clock.
|
||||||
|
typedef typename clock_type::time_point time_point;
|
||||||
|
|
||||||
|
/// The wait traits type.
|
||||||
|
typedef WaitTraits traits_type;
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer without setting an expiry time. The
|
||||||
|
* expires_at() or expires_after() functions must be called to set an expiry
|
||||||
|
* time before the timer can be waited on.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*/
|
||||||
|
explicit basic_waitable_timer(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer without setting an expiry time. The
|
||||||
|
* expires_at() or expires_after() functions must be called to set an expiry
|
||||||
|
* time before the timer can be waited on.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_waitable_timer(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor object that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||||
|
* as an absolute time.
|
||||||
|
*/
|
||||||
|
basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||||
|
* as an absolute time.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_waitable_timer(ExecutionContext& context,
|
||||||
|
const time_point& expiry_time,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the timer will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
basic_waitable_timer(const executor_type& ex, const duration& expiry_time)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_after(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_after");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor to set a particular expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This constructor creates a timer and sets the expiry time.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the timer.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_waitable_timer(ExecutionContext& context,
|
||||||
|
const duration& expiry_time,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().expires_after(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_after");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_waitable_timer from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a timer from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_waitable_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_waitable_timer(basic_waitable_timer&& other)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_waitable_timer from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a timer from one object to another. Cancels
|
||||||
|
* any outstanding asynchronous operations associated with the target object.
|
||||||
|
*
|
||||||
|
* @param other The other basic_waitable_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_waitable_timer& operator=(basic_waitable_timer&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All timers have access to each other's implementations.
|
||||||
|
template <typename Clock1, typename WaitTraits1, typename Executor1>
|
||||||
|
friend class basic_waitable_timer;
|
||||||
|
|
||||||
|
/// Move-construct a basic_waitable_timer from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a timer from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_waitable_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
basic_waitable_timer(
|
||||||
|
basic_waitable_timer<Clock, WaitTraits, Executor1>&& other,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_waitable_timer from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a timer from one object to another. Cancels
|
||||||
|
* any outstanding asynchronous operations associated with the target object.
|
||||||
|
*
|
||||||
|
* @param other The other basic_waitable_timer object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename Executor1>
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<Executor1, Executor>::value,
|
||||||
|
basic_waitable_timer&
|
||||||
|
>::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other)
|
||||||
|
{
|
||||||
|
basic_waitable_timer tmp(std::move(other));
|
||||||
|
impl_ = std::move(tmp.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the timer.
|
||||||
|
/**
|
||||||
|
* This function destroys the timer, cancelling any outstanding asynchronous
|
||||||
|
* wait operations associated with the timer as if by calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_waitable_timer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel any asynchronous operations that are waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the timer. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use non-error_code overload.) Cancel any asynchronous
|
||||||
|
/// operations that are waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of any pending asynchronous wait
|
||||||
|
* operations against the timer. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel() is called, then the
|
||||||
|
* handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Cancels one asynchronous operation that is waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of one pending asynchronous wait
|
||||||
|
* operation against the timer. Handlers are cancelled in FIFO order. The
|
||||||
|
* handler for the cancelled operation will be invoked with the
|
||||||
|
* asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled. That is,
|
||||||
|
* either 0 or 1.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel_one() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel_one()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().cancel_one(
|
||||||
|
impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel_one");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use non-error_code overload.) Cancels one asynchronous
|
||||||
|
/// operation that is waiting on the timer.
|
||||||
|
/**
|
||||||
|
* This function forces the completion of one pending asynchronous wait
|
||||||
|
* operation against the timer. Handlers are cancelled in FIFO order. The
|
||||||
|
* handler for the cancelled operation will be invoked with the
|
||||||
|
* asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* Cancelling the timer does not change the expiry time.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled. That is,
|
||||||
|
* either 0 or 1.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when cancel_one() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t cancel_one(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().cancel_one(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
|
||||||
|
/// time.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the timer's current expiry time.
|
||||||
|
* Whether the timer has expired or not does not affect this value.
|
||||||
|
*/
|
||||||
|
time_point expires_at() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_at(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Get the timer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the timer's current expiry time.
|
||||||
|
* Whether the timer has expired or not does not affect this value.
|
||||||
|
*/
|
||||||
|
time_point expiry() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().expiry(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the timer's expiry time as an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_at() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_at(const time_point& expiry_time)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().expires_at(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_at");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use non-error_code overload.) Set the timer's expiry time as
|
||||||
|
/// an absolute time.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_at() is called, then
|
||||||
|
* the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_at(const time_point& expiry_time,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_at(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Set the timer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_after() is called,
|
||||||
|
* then the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_after(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().expires_after(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_after");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
/// (Deprecated: Use expiry().) Get the timer's expiry time relative to now.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the timer's current expiry time.
|
||||||
|
* Whether the timer has expired or not does not affect this value.
|
||||||
|
*/
|
||||||
|
duration expires_from_now() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_from_now(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expires_after().) Set the timer's expiry time relative
|
||||||
|
/// to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_from_now() is called,
|
||||||
|
* then the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_from_now(const duration& expiry_time)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
asio::detail::throw_error(ec, "expires_from_now");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (Deprecated: Use expires_after().) Set the timer's expiry time relative
|
||||||
|
/// to now.
|
||||||
|
/**
|
||||||
|
* This function sets the expiry time. Any pending asynchronous wait
|
||||||
|
* operations will be cancelled. The handler for each cancelled operation will
|
||||||
|
* be invoked with the asio::error::operation_aborted error code.
|
||||||
|
*
|
||||||
|
* @param expiry_time The expiry time to be used for the timer.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @return The number of asynchronous operations that were cancelled.
|
||||||
|
*
|
||||||
|
* @note If the timer has already expired when expires_from_now() is called,
|
||||||
|
* then the handlers for asynchronous wait operations will:
|
||||||
|
*
|
||||||
|
* @li have already been invoked; or
|
||||||
|
*
|
||||||
|
* @li have been queued for invocation in the near future.
|
||||||
|
*
|
||||||
|
* These handlers can no longer be cancelled, and therefore are passed an
|
||||||
|
* error code that indicates the successful completion of the wait operation.
|
||||||
|
*/
|
||||||
|
std::size_t expires_from_now(const duration& expiry_time,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().expires_from_now(
|
||||||
|
impl_.get_implementation(), expiry_time, ec);
|
||||||
|
}
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
/// Perform a blocking wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function is used to wait for the timer to expire. This function
|
||||||
|
* blocks and does not return until the timer has expired.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().wait(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a blocking wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function is used to wait for the timer to expire. This function
|
||||||
|
* blocks and does not return until the timer has expired.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
void wait(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().wait(impl_.get_implementation(), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous wait on the timer.
|
||||||
|
/**
|
||||||
|
* This function may be used to initiate an asynchronous wait against the
|
||||||
|
* timer. It is an initiating function for an @ref asynchronous_operation,
|
||||||
|
* and always returns immediately.
|
||||||
|
*
|
||||||
|
* For each call to async_wait(), the completion handler will be called
|
||||||
|
* exactly once. The completion handler will be called when:
|
||||||
|
*
|
||||||
|
* @li The timer has expired.
|
||||||
|
*
|
||||||
|
* @li The timer was cancelled, in which case the handler is passed the error
|
||||||
|
* code asio::error::operation_aborted.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the timer expires. Potential
|
||||||
|
* completion tokens include @ref use_future, @ref use_awaitable, @ref
|
||||||
|
* yield_context, or a function object with the correct completion signature.
|
||||||
|
* The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error // Result of operation.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code) @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* This asynchronous operation supports cancellation for the following
|
||||||
|
* asio::cancellation_type values:
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::terminal
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::partial
|
||||||
|
*
|
||||||
|
* @li @c cancellation_type::total
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))
|
||||||
|
WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WaitToken,
|
||||||
|
void (asio::error_code))
|
||||||
|
async_wait(
|
||||||
|
ASIO_MOVE_ARG(WaitToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WaitToken, void (asio::error_code)>(
|
||||||
|
initiate_async_wait(this), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_waitable_timer(const basic_waitable_timer&) ASIO_DELETED;
|
||||||
|
basic_waitable_timer& operator=(
|
||||||
|
const basic_waitable_timer&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_wait
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_wait(basic_waitable_timer* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WaitHandler>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WaitHandler) handler) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WaitHandler.
|
||||||
|
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_wait(
|
||||||
|
self_->impl_.get_implementation(),
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_waitable_timer* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
detail::io_object_impl<
|
||||||
|
detail::deadline_timer_service<
|
||||||
|
detail::chrono_time_traits<Clock, WaitTraits> >,
|
||||||
|
executor_type > impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_WAITABLE_TIMER_HPP
|
525
lib/asio/include/asio/basic_writable_pipe.hpp
Normal file
525
lib/asio/include/asio/basic_writable_pipe.hpp
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
//
|
||||||
|
// basic_writable_pipe.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_WRITABLE_PIPE_HPP
|
||||||
|
#define ASIO_BASIC_WRITABLE_PIPE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_PIPE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "asio/any_io_executor.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/handler_type_requirements.hpp"
|
||||||
|
#include "asio/detail/io_object_impl.hpp"
|
||||||
|
#include "asio/detail/non_const_lvalue.hpp"
|
||||||
|
#include "asio/detail/throw_error.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
# include "asio/detail/win_iocp_handle_service.hpp"
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
# include "asio/detail/io_uring_descriptor_service.hpp"
|
||||||
|
#else
|
||||||
|
# include "asio/detail/reactive_descriptor_service.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Provides pipe functionality.
|
||||||
|
/**
|
||||||
|
* The basic_writable_pipe class provides a wrapper over pipe
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*/
|
||||||
|
template <typename Executor = any_io_executor>
|
||||||
|
class basic_writable_pipe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
/// Rebinds the pipe type to another executor.
|
||||||
|
template <typename Executor1>
|
||||||
|
struct rebind_executor
|
||||||
|
{
|
||||||
|
/// The pipe type when rebound to the specified executor.
|
||||||
|
typedef basic_writable_pipe<Executor1> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The native representation of a pipe.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef implementation_defined native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IOCP)
|
||||||
|
typedef detail::win_iocp_handle_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
typedef detail::io_uring_descriptor_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#else
|
||||||
|
typedef detail::reactive_descriptor_service::native_handle_type
|
||||||
|
native_handle_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// A basic_writable_pipe is always the lowest layer.
|
||||||
|
typedef basic_writable_pipe lowest_layer_type;
|
||||||
|
|
||||||
|
/// Construct a basic_writable_pipe without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe without opening it.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the pipe will use, by default, to dispatch
|
||||||
|
* handlers for any asynchronous operations performed on the pipe.
|
||||||
|
*/
|
||||||
|
explicit basic_writable_pipe(const executor_type& ex)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_writable_pipe without opening it.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe without opening it.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the pipe will use, by default, to dispatch handlers for any asynchronous
|
||||||
|
* operations performed on the pipe.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
explicit basic_writable_pipe(ExecutionContext& context,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value,
|
||||||
|
defaulted_constraint
|
||||||
|
>::type = defaulted_constraint())
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_writable_pipe on an existing native pipe.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe object to hold an existing native
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param ex The I/O executor that the pipe will use, by default, to
|
||||||
|
* dispatch handlers for any asynchronous operations performed on the
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
basic_writable_pipe(const executor_type& ex,
|
||||||
|
const native_handle_type& native_pipe)
|
||||||
|
: impl_(0, ex)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a basic_writable_pipe on an existing native pipe.
|
||||||
|
/**
|
||||||
|
* This constructor creates a pipe object to hold an existing native
|
||||||
|
* pipe.
|
||||||
|
*
|
||||||
|
* @param context An execution context which provides the I/O executor that
|
||||||
|
* the pipe will use, by default, to dispatch handlers for any
|
||||||
|
* asynchronous operations performed on the pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
basic_writable_pipe(ExecutionContext& context,
|
||||||
|
const native_handle_type& native_pipe,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: impl_(0, 0, context)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(),
|
||||||
|
native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move-construct a basic_writable_pipe from another.
|
||||||
|
/**
|
||||||
|
* This constructor moves a pipe from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_writable_pipe object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_writable_pipe(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_writable_pipe(basic_writable_pipe&& other)
|
||||||
|
: impl_(std::move(other.impl_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a basic_writable_pipe from another.
|
||||||
|
/**
|
||||||
|
* This assignment operator moves a pipe from one object to another.
|
||||||
|
*
|
||||||
|
* @param other The other basic_writable_pipe object from which the move will
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @note Following the move, the moved-from object is in the same state as if
|
||||||
|
* constructed using the @c basic_writable_pipe(const executor_type&)
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
basic_writable_pipe& operator=(basic_writable_pipe&& other)
|
||||||
|
{
|
||||||
|
impl_ = std::move(other.impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destroys the pipe.
|
||||||
|
/**
|
||||||
|
* This function destroys the pipe, cancelling any outstanding
|
||||||
|
* asynchronous wait operations associated with the pipe as if by
|
||||||
|
* calling @c cancel.
|
||||||
|
*/
|
||||||
|
~basic_writable_pipe()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_.get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_writable_pipe cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||||
|
* is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
/**
|
||||||
|
* This function returns a const reference to the lowest layer in a stack of
|
||||||
|
* layers. Since a basic_writable_pipe cannot contain any further layers, it
|
||||||
|
* simply returns a reference to itself.
|
||||||
|
*
|
||||||
|
* @return A const reference to the lowest layer in the stack of layers.
|
||||||
|
* Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native pipe to the pipe.
|
||||||
|
/*
|
||||||
|
* This function opens the pipe to hold an existing native pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void assign(const native_handle_type& native_pipe)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
|
||||||
|
asio::detail::throw_error(ec, "assign");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign an existing native pipe to the pipe.
|
||||||
|
/*
|
||||||
|
* This function opens the pipe to hold an existing native pipe.
|
||||||
|
*
|
||||||
|
* @param native_pipe A native pipe.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine whether the pipe is open.
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return impl_.get_service().is_open(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to close the pipe. Any asynchronous write operations
|
||||||
|
* will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to close the pipe. Any asynchronous write operations
|
||||||
|
* will be cancelled immediately, and will complete with the
|
||||||
|
* asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the native pipe representation.
|
||||||
|
/**
|
||||||
|
* This function may be used to obtain the underlying representation of the
|
||||||
|
* pipe. This is intended to allow access to native pipe
|
||||||
|
* functionality that is not otherwise provided.
|
||||||
|
*/
|
||||||
|
native_handle_type native_handle()
|
||||||
|
{
|
||||||
|
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the pipe.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous write operations to
|
||||||
|
* finish immediately, and the handlers for cancelled operations will be
|
||||||
|
* passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
asio::detail::throw_error(ec, "cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all asynchronous operations associated with the pipe.
|
||||||
|
/**
|
||||||
|
* This function causes all outstanding asynchronous write operations to
|
||||||
|
* finish immediately, and the handlers for cancelled operations will be
|
||||||
|
* passed the asio::error::operation_aborted error.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the pipe. The function call will
|
||||||
|
* block until one or more bytes of the data has been written successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the pipe.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure. An error code of
|
||||||
|
* asio::error::eof indicates that the connection was closed by the
|
||||||
|
* peer.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* pipe.write_some(asio::buffer(data, size));
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
asio::error_code ec;
|
||||||
|
std::size_t s = impl_.get_service().write_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
asio::detail::throw_error(ec, "write_some");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write some data to the pipe.
|
||||||
|
/**
|
||||||
|
* This function is used to write data to the pipe. The function call will
|
||||||
|
* block until one or more bytes of the data has been written successfully,
|
||||||
|
* or until an error occurs.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the pipe.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||||
|
*
|
||||||
|
* @note The write_some operation may not transmit all of the data to the
|
||||||
|
* peer. Consider using the @ref write function if you need to ensure that
|
||||||
|
* all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return impl_.get_service().write_some(
|
||||||
|
impl_.get_implementation(), buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write.
|
||||||
|
/**
|
||||||
|
* This function is used to asynchronously write data to the pipe. It is an
|
||||||
|
* initiating function for an @ref asynchronous_operation, and always returns
|
||||||
|
* immediately.
|
||||||
|
*
|
||||||
|
* @param buffers One or more data buffers to be written to the pipe.
|
||||||
|
* Although the buffers object may be copied as necessary, ownership of the
|
||||||
|
* underlying memory blocks is retained by the caller, which must guarantee
|
||||||
|
* that they remain valid until the completion handler is called.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler, which will be called when the write completes.
|
||||||
|
* Potential completion tokens include @ref use_future, @ref use_awaitable,
|
||||||
|
* @ref yield_context, or a function object with the correct completion
|
||||||
|
* signature. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(
|
||||||
|
* const asio::error_code& error, // Result of operation.
|
||||||
|
* std::size_t bytes_transferred // Number of bytes written.
|
||||||
|
* ); @endcode
|
||||||
|
* Regardless of whether the asynchronous operation completes immediately or
|
||||||
|
* not, the completion handler will not be invoked from within this function.
|
||||||
|
* On immediate completion, invocation of the handler will be performed in a
|
||||||
|
* manner equivalent to using asio::post().
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*
|
||||||
|
* @note The write operation may not transmit all of the data to the peer.
|
||||||
|
* Consider using the @ref async_write function if you need to ensure that all
|
||||||
|
* data is written before the asynchronous operation completes.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* To write a single data buffer use the @ref buffer function as follows:
|
||||||
|
* @code
|
||||||
|
* pipe.async_write_some(asio::buffer(data, size), handler);
|
||||||
|
* @endcode
|
||||||
|
* See the @ref buffer documentation for information on writing multiple
|
||||||
|
* buffers in one go, and how to use it with arrays, boost::array or
|
||||||
|
* std::vector.
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return async_initiate<WriteToken,
|
||||||
|
void (asio::error_code, std::size_t)>(
|
||||||
|
initiate_async_write_some(this), token, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
basic_writable_pipe(const basic_writable_pipe&) ASIO_DELETED;
|
||||||
|
basic_writable_pipe& operator=(const basic_writable_pipe&) ASIO_DELETED;
|
||||||
|
|
||||||
|
class initiate_async_write_some
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
explicit initiate_async_write_some(basic_writable_pipe* self)
|
||||||
|
: self_(self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return self_->get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename WriteHandler, typename ConstBufferSequence>
|
||||||
|
void operator()(ASIO_MOVE_ARG(WriteHandler) handler,
|
||||||
|
const ConstBufferSequence& buffers) const
|
||||||
|
{
|
||||||
|
// If you get an error on the following line it means that your handler
|
||||||
|
// does not meet the documented type requirements for a WriteHandler.
|
||||||
|
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||||
|
|
||||||
|
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||||
|
self_->impl_.get_service().async_write_some(
|
||||||
|
self_->impl_.get_implementation(), buffers,
|
||||||
|
handler2.value, self_->impl_.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
basic_writable_pipe* self_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;
|
||||||
|
#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)
|
||||||
|
detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;
|
||||||
|
#else
|
||||||
|
detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_PIPE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_WRITABLE_PIPE_HPP
|
722
lib/asio/include/asio/bind_allocator.hpp
Normal file
722
lib/asio/include/asio/bind_allocator.hpp
Normal file
@ -0,0 +1,722 @@
|
|||||||
|
//
|
||||||
|
// bind_allocator.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BIND_ALLOCATOR_HPP
|
||||||
|
#define ASIO_BIND_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/detail/variadic_templates.hpp"
|
||||||
|
#include "asio/associated_allocator.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef result_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct allocator_binder_result_type
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef void result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct allocator_binder_result_type<T,
|
||||||
|
typename void_type<typename T::result_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::result_type result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct allocator_binder_result_type<R(*)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct allocator_binder_result_type<R(&)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct allocator_binder_result_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct allocator_binder_result_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct allocator_binder_result_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct allocator_binder_result_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct allocator_binder_argument_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct allocator_binder_argument_type<T,
|
||||||
|
typename void_type<typename T::argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct allocator_binder_argument_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct allocator_binder_argument_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedefs first_argument_type and
|
||||||
|
// second_argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct allocator_binder_argument_types {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct allocator_binder_argument_types<T,
|
||||||
|
typename void_type<typename T::first_argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::first_argument_type first_argument_type;
|
||||||
|
typedef typename T::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct allocator_binder_argument_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct allocator_binder_argument_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to enable SFINAE on zero-argument operator() below.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct allocator_binder_result_of0
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct allocator_binder_result_of0<T,
|
||||||
|
typename void_type<typename result_of<T()>::type>::type>
|
||||||
|
{
|
||||||
|
typedef typename result_of<T()>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// A call wrapper type to bind an allocator of type @c Allocator
|
||||||
|
/// to an object of type @c T.
|
||||||
|
template <typename T, typename Allocator>
|
||||||
|
class allocator_binder
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: public detail::allocator_binder_result_type<T>,
|
||||||
|
public detail::allocator_binder_argument_type<T>,
|
||||||
|
public detail::allocator_binder_argument_types<T>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the target object.
|
||||||
|
typedef T target_type;
|
||||||
|
|
||||||
|
/// The type of the associated allocator.
|
||||||
|
typedef Allocator allocator_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The return type if a function.
|
||||||
|
/**
|
||||||
|
* The type of @c result_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to function type, @c result_type is a synonym for
|
||||||
|
* the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c result_type, then @c
|
||||||
|
* result_type is a synonym for @c T::result_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c result_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below result_type;
|
||||||
|
|
||||||
|
/// The type of the function's argument.
|
||||||
|
/**
|
||||||
|
* The type of @c argument_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting a single argument,
|
||||||
|
* @c argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c argument_type, then @c
|
||||||
|
* argument_type is a synonym for @c T::argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's first argument.
|
||||||
|
/**
|
||||||
|
* The type of @c first_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* first_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c first_argument_type is a synonym for @c T::first_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c first_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below first_argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's second argument.
|
||||||
|
/**
|
||||||
|
* The type of @c second_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* second_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c second_argument_type is a synonym for @c T::second_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c second_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below second_argument_type;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Construct an allocator wrapper for the specified object.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
allocator_binder(const allocator_type& s,
|
||||||
|
ASIO_MOVE_ARG(U) u)
|
||||||
|
: allocator_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
allocator_binder(const allocator_binder& other)
|
||||||
|
: allocator_(other.get_allocator()),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy, but specify a different allocator.
|
||||||
|
allocator_binder(const allocator_type& s,
|
||||||
|
const allocator_binder& other)
|
||||||
|
: allocator_(s),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different allocator wrapper type.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the @c Allocator type is
|
||||||
|
* constructible from type @c OtherAllocator, and the type @c T is
|
||||||
|
* constructible from type @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherAllocator>
|
||||||
|
allocator_binder(
|
||||||
|
const allocator_binder<U, OtherAllocator>& other)
|
||||||
|
: allocator_(other.get_allocator()),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different allocator wrapper type, but
|
||||||
|
/// specify a different allocator.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherAllocator>
|
||||||
|
allocator_binder(const allocator_type& s,
|
||||||
|
const allocator_binder<U, OtherAllocator>& other)
|
||||||
|
: allocator_(s),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Move constructor.
|
||||||
|
allocator_binder(allocator_binder&& other)
|
||||||
|
: allocator_(ASIO_MOVE_CAST(allocator_type)(
|
||||||
|
other.get_allocator())),
|
||||||
|
target_(ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct the target object, but specify a different allocator.
|
||||||
|
allocator_binder(const allocator_type& s,
|
||||||
|
allocator_binder&& other)
|
||||||
|
: allocator_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different allocator wrapper type.
|
||||||
|
template <typename U, typename OtherAllocator>
|
||||||
|
allocator_binder(
|
||||||
|
allocator_binder<U, OtherAllocator>&& other)
|
||||||
|
: allocator_(ASIO_MOVE_CAST(OtherAllocator)(
|
||||||
|
other.get_allocator())),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different allocator wrapper type, but
|
||||||
|
/// specify a different allocator.
|
||||||
|
template <typename U, typename OtherAllocator>
|
||||||
|
allocator_binder(const allocator_type& s,
|
||||||
|
allocator_binder<U, OtherAllocator>&& other)
|
||||||
|
: allocator_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
~allocator_binder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
target_type& get() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
const target_type& get() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain the associated allocator.
|
||||||
|
allocator_type get_allocator() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return allocator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <typename... Args> auto operator()(Args&& ...);
|
||||||
|
template <typename... Args> auto operator()(Args&& ...) const;
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
return target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typename detail::allocator_binder_result_of0<T>::type operator()()
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename detail::allocator_binder_result_of0<T>::type
|
||||||
|
operator()() const
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BINDER_CALL_DEF
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typedef typename detail::allocator_binder_result_type<
|
||||||
|
T>::result_type_or_void result_type_or_void;
|
||||||
|
|
||||||
|
result_type_or_void operator()()
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type_or_void operator()() const
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BINDER_CALL_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
private:
|
||||||
|
Allocator allocator_;
|
||||||
|
T target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Associate an object of type @c T with an allocator of type
|
||||||
|
/// @c Allocator.
|
||||||
|
template <typename Allocator, typename T>
|
||||||
|
ASIO_NODISCARD inline allocator_binder<typename decay<T>::type, Allocator>
|
||||||
|
bind_allocator(const Allocator& s, ASIO_MOVE_ARG(T) t)
|
||||||
|
{
|
||||||
|
return allocator_binder<
|
||||||
|
typename decay<T>::type, Allocator>(
|
||||||
|
s, ASIO_MOVE_CAST(T)(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult,
|
||||||
|
typename Allocator, typename = void>
|
||||||
|
struct allocator_binder_async_result_completion_handler_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename Allocator>
|
||||||
|
struct allocator_binder_async_result_completion_handler_type<
|
||||||
|
TargetAsyncResult, Allocator,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::completion_handler_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef allocator_binder<
|
||||||
|
typename TargetAsyncResult::completion_handler_type, Allocator>
|
||||||
|
completion_handler_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename = void>
|
||||||
|
struct allocator_binder_async_result_return_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult>
|
||||||
|
struct allocator_binder_async_result_return_type<
|
||||||
|
TargetAsyncResult,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::return_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef typename TargetAsyncResult::return_type return_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename Allocator, typename Signature>
|
||||||
|
class async_result<allocator_binder<T, Allocator>, Signature> :
|
||||||
|
public detail::allocator_binder_async_result_completion_handler_type<
|
||||||
|
async_result<T, Signature>, Allocator>,
|
||||||
|
public detail::allocator_binder_async_result_return_type<
|
||||||
|
async_result<T, Signature> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit async_result(allocator_binder<T, Allocator>& b)
|
||||||
|
: target_(b.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typename async_result<T, Signature>::return_type get()
|
||||||
|
{
|
||||||
|
return target_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Initiation>
|
||||||
|
struct init_wrapper
|
||||||
|
{
|
||||||
|
template <typename Init>
|
||||||
|
init_wrapper(const Allocator& allocator, ASIO_MOVE_ARG(Init) init)
|
||||||
|
: allocator_(allocator),
|
||||||
|
initiation_(ASIO_MOVE_CAST(Init)(init))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
allocator_binder<
|
||||||
|
typename decay<Handler>::type, Allocator>(
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
allocator_binder<
|
||||||
|
typename decay<Handler>::type, Allocator>(
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
allocator_binder<
|
||||||
|
typename decay<Handler>::type, Allocator>(
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
allocator_binder<
|
||||||
|
typename decay<Handler>::type, Allocator>(
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)( \
|
||||||
|
allocator_binder< \
|
||||||
|
typename decay<Handler>::type, Allocator>( \
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
initiation_( \
|
||||||
|
allocator_binder< \
|
||||||
|
typename decay<Handler>::type, Allocator>( \
|
||||||
|
allocator_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INIT_WRAPPER_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
Allocator allocator_;
|
||||||
|
Initiation initiation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken, typename... Args>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get(),
|
||||||
|
declval<ASIO_MOVE_ARG(Args)>()...)))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_allocator(),
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get(), ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get())))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_allocator(),
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INITIATE_DEF(n) \
|
||||||
|
template <typename Initiation, typename RawCompletionToken, \
|
||||||
|
ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
|
||||||
|
(async_initiate<T, Signature>( \
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(), \
|
||||||
|
declval<RawCompletionToken>().get(), \
|
||||||
|
ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
|
||||||
|
initiate( \
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation, \
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return async_initiate<T, Signature>( \
|
||||||
|
init_wrapper<typename decay<Initiation>::type>( \
|
||||||
|
token.get_allocator(), \
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)), \
|
||||||
|
token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INITIATE_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
private:
|
||||||
|
async_result(const async_result&) ASIO_DELETED;
|
||||||
|
async_result& operator=(const async_result&) ASIO_DELETED;
|
||||||
|
|
||||||
|
async_result<T, Signature> target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename> class Associator,
|
||||||
|
typename T, typename Allocator, typename DefaultCandidate>
|
||||||
|
struct associator<Associator,
|
||||||
|
allocator_binder<T, Allocator>,
|
||||||
|
DefaultCandidate>
|
||||||
|
{
|
||||||
|
typedef typename Associator<T, DefaultCandidate>::type type;
|
||||||
|
|
||||||
|
static type get(const allocator_binder<T, Allocator>& b,
|
||||||
|
const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return Associator<T, DefaultCandidate>::get(b.get(), c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Allocator, typename Allocator1>
|
||||||
|
struct associated_allocator<
|
||||||
|
allocator_binder<T, Allocator>,
|
||||||
|
Allocator1>
|
||||||
|
{
|
||||||
|
typedef Allocator type;
|
||||||
|
|
||||||
|
static type get(const allocator_binder<T, Allocator>& b,
|
||||||
|
const Allocator1& = Allocator1()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return b.get_allocator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BIND_ALLOCATOR_HPP
|
724
lib/asio/include/asio/bind_cancellation_slot.hpp
Normal file
724
lib/asio/include/asio/bind_cancellation_slot.hpp
Normal file
@ -0,0 +1,724 @@
|
|||||||
|
//
|
||||||
|
// bind_cancellation_slot.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BIND_CANCELLATION_SLOT_HPP
|
||||||
|
#define ASIO_BIND_CANCELLATION_SLOT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/detail/variadic_templates.hpp"
|
||||||
|
#include "asio/associated_cancellation_slot.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef result_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct cancellation_slot_binder_result_type
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef void result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct cancellation_slot_binder_result_type<T,
|
||||||
|
typename void_type<typename T::result_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::result_type result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct cancellation_slot_binder_result_type<R(*)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct cancellation_slot_binder_result_type<R(&)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct cancellation_slot_binder_result_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct cancellation_slot_binder_result_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct cancellation_slot_binder_result_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct cancellation_slot_binder_result_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct cancellation_slot_binder_argument_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct cancellation_slot_binder_argument_type<T,
|
||||||
|
typename void_type<typename T::argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct cancellation_slot_binder_argument_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct cancellation_slot_binder_argument_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedefs first_argument_type and
|
||||||
|
// second_argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct cancellation_slot_binder_argument_types {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct cancellation_slot_binder_argument_types<T,
|
||||||
|
typename void_type<typename T::first_argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::first_argument_type first_argument_type;
|
||||||
|
typedef typename T::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to enable SFINAE on zero-argument operator() below.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct cancellation_slot_binder_result_of0
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct cancellation_slot_binder_result_of0<T,
|
||||||
|
typename void_type<typename result_of<T()>::type>::type>
|
||||||
|
{
|
||||||
|
typedef typename result_of<T()>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// A call wrapper type to bind a cancellation slot of type @c CancellationSlot
|
||||||
|
/// to an object of type @c T.
|
||||||
|
template <typename T, typename CancellationSlot>
|
||||||
|
class cancellation_slot_binder
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: public detail::cancellation_slot_binder_result_type<T>,
|
||||||
|
public detail::cancellation_slot_binder_argument_type<T>,
|
||||||
|
public detail::cancellation_slot_binder_argument_types<T>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the target object.
|
||||||
|
typedef T target_type;
|
||||||
|
|
||||||
|
/// The type of the associated cancellation slot.
|
||||||
|
typedef CancellationSlot cancellation_slot_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The return type if a function.
|
||||||
|
/**
|
||||||
|
* The type of @c result_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to function type, @c result_type is a synonym for
|
||||||
|
* the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c result_type, then @c
|
||||||
|
* result_type is a synonym for @c T::result_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c result_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below result_type;
|
||||||
|
|
||||||
|
/// The type of the function's argument.
|
||||||
|
/**
|
||||||
|
* The type of @c argument_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting a single argument,
|
||||||
|
* @c argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c argument_type, then @c
|
||||||
|
* argument_type is a synonym for @c T::argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's first argument.
|
||||||
|
/**
|
||||||
|
* The type of @c first_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* first_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c first_argument_type is a synonym for @c T::first_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c first_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below first_argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's second argument.
|
||||||
|
/**
|
||||||
|
* The type of @c second_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* second_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c second_argument_type is a synonym for @c T::second_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c second_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below second_argument_type;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Construct a cancellation slot wrapper for the specified object.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
cancellation_slot_binder(const cancellation_slot_type& s,
|
||||||
|
ASIO_MOVE_ARG(U) u)
|
||||||
|
: slot_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
cancellation_slot_binder(const cancellation_slot_binder& other)
|
||||||
|
: slot_(other.get_cancellation_slot()),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy, but specify a different cancellation slot.
|
||||||
|
cancellation_slot_binder(const cancellation_slot_type& s,
|
||||||
|
const cancellation_slot_binder& other)
|
||||||
|
: slot_(s),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different cancellation slot wrapper type.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the @c CancellationSlot type is
|
||||||
|
* constructible from type @c OtherCancellationSlot, and the type @c T is
|
||||||
|
* constructible from type @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherCancellationSlot>
|
||||||
|
cancellation_slot_binder(
|
||||||
|
const cancellation_slot_binder<U, OtherCancellationSlot>& other)
|
||||||
|
: slot_(other.get_cancellation_slot()),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different cancellation slot wrapper type, but
|
||||||
|
/// specify a different cancellation slot.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherCancellationSlot>
|
||||||
|
cancellation_slot_binder(const cancellation_slot_type& s,
|
||||||
|
const cancellation_slot_binder<U, OtherCancellationSlot>& other)
|
||||||
|
: slot_(s),
|
||||||
|
target_(other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Move constructor.
|
||||||
|
cancellation_slot_binder(cancellation_slot_binder&& other)
|
||||||
|
: slot_(ASIO_MOVE_CAST(cancellation_slot_type)(
|
||||||
|
other.get_cancellation_slot())),
|
||||||
|
target_(ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct the target object, but specify a different cancellation
|
||||||
|
/// slot.
|
||||||
|
cancellation_slot_binder(const cancellation_slot_type& s,
|
||||||
|
cancellation_slot_binder&& other)
|
||||||
|
: slot_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different cancellation slot wrapper type.
|
||||||
|
template <typename U, typename OtherCancellationSlot>
|
||||||
|
cancellation_slot_binder(
|
||||||
|
cancellation_slot_binder<U, OtherCancellationSlot>&& other)
|
||||||
|
: slot_(ASIO_MOVE_CAST(OtherCancellationSlot)(
|
||||||
|
other.get_cancellation_slot())),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different cancellation slot wrapper type, but
|
||||||
|
/// specify a different cancellation slot.
|
||||||
|
template <typename U, typename OtherCancellationSlot>
|
||||||
|
cancellation_slot_binder(const cancellation_slot_type& s,
|
||||||
|
cancellation_slot_binder<U, OtherCancellationSlot>&& other)
|
||||||
|
: slot_(s),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
~cancellation_slot_binder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
target_type& get() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
const target_type& get() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain the associated cancellation slot.
|
||||||
|
cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return slot_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <typename... Args> auto operator()(Args&& ...);
|
||||||
|
template <typename... Args> auto operator()(Args&& ...) const;
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
return target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typename detail::cancellation_slot_binder_result_of0<T>::type operator()()
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename detail::cancellation_slot_binder_result_of0<T>::type
|
||||||
|
operator()() const
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BINDER_CALL_DEF
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typedef typename detail::cancellation_slot_binder_result_type<
|
||||||
|
T>::result_type_or_void result_type_or_void;
|
||||||
|
|
||||||
|
result_type_or_void operator()()
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type_or_void operator()() const
|
||||||
|
{
|
||||||
|
return target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BINDER_CALL_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
private:
|
||||||
|
CancellationSlot slot_;
|
||||||
|
T target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Associate an object of type @c T with a cancellation slot of type
|
||||||
|
/// @c CancellationSlot.
|
||||||
|
template <typename CancellationSlot, typename T>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
cancellation_slot_binder<typename decay<T>::type, CancellationSlot>
|
||||||
|
bind_cancellation_slot(const CancellationSlot& s, ASIO_MOVE_ARG(T) t)
|
||||||
|
{
|
||||||
|
return cancellation_slot_binder<
|
||||||
|
typename decay<T>::type, CancellationSlot>(
|
||||||
|
s, ASIO_MOVE_CAST(T)(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult,
|
||||||
|
typename CancellationSlot, typename = void>
|
||||||
|
struct cancellation_slot_binder_async_result_completion_handler_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename CancellationSlot>
|
||||||
|
struct cancellation_slot_binder_async_result_completion_handler_type<
|
||||||
|
TargetAsyncResult, CancellationSlot,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::completion_handler_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef cancellation_slot_binder<
|
||||||
|
typename TargetAsyncResult::completion_handler_type, CancellationSlot>
|
||||||
|
completion_handler_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename = void>
|
||||||
|
struct cancellation_slot_binder_async_result_return_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult>
|
||||||
|
struct cancellation_slot_binder_async_result_return_type<
|
||||||
|
TargetAsyncResult,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::return_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef typename TargetAsyncResult::return_type return_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename CancellationSlot, typename Signature>
|
||||||
|
class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :
|
||||||
|
public detail::cancellation_slot_binder_async_result_completion_handler_type<
|
||||||
|
async_result<T, Signature>, CancellationSlot>,
|
||||||
|
public detail::cancellation_slot_binder_async_result_return_type<
|
||||||
|
async_result<T, Signature> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)
|
||||||
|
: target_(b.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typename async_result<T, Signature>::return_type get()
|
||||||
|
{
|
||||||
|
return target_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Initiation>
|
||||||
|
struct init_wrapper
|
||||||
|
{
|
||||||
|
template <typename Init>
|
||||||
|
init_wrapper(const CancellationSlot& slot, ASIO_MOVE_ARG(Init) init)
|
||||||
|
: slot_(slot),
|
||||||
|
initiation_(ASIO_MOVE_CAST(Init)(init))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
cancellation_slot_binder<
|
||||||
|
typename decay<Handler>::type, CancellationSlot>(
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
cancellation_slot_binder<
|
||||||
|
typename decay<Handler>::type, CancellationSlot>(
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
cancellation_slot_binder<
|
||||||
|
typename decay<Handler>::type, CancellationSlot>(
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
cancellation_slot_binder<
|
||||||
|
typename decay<Handler>::type, CancellationSlot>(
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)( \
|
||||||
|
cancellation_slot_binder< \
|
||||||
|
typename decay<Handler>::type, CancellationSlot>( \
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
initiation_( \
|
||||||
|
cancellation_slot_binder< \
|
||||||
|
typename decay<Handler>::type, CancellationSlot>( \
|
||||||
|
slot_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INIT_WRAPPER_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
CancellationSlot slot_;
|
||||||
|
Initiation initiation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken, typename... Args>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get(),
|
||||||
|
declval<ASIO_MOVE_ARG(Args)>()...)))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_cancellation_slot(),
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get(), ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get())))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_cancellation_slot(),
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INITIATE_DEF(n) \
|
||||||
|
template <typename Initiation, typename RawCompletionToken, \
|
||||||
|
ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
|
||||||
|
(async_initiate<T, Signature>( \
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(), \
|
||||||
|
declval<RawCompletionToken>().get(), \
|
||||||
|
ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
|
||||||
|
initiate( \
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation, \
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return async_initiate<T, Signature>( \
|
||||||
|
init_wrapper<typename decay<Initiation>::type>( \
|
||||||
|
token.get_cancellation_slot(), \
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation)), \
|
||||||
|
token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INITIATE_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
private:
|
||||||
|
async_result(const async_result&) ASIO_DELETED;
|
||||||
|
async_result& operator=(const async_result&) ASIO_DELETED;
|
||||||
|
|
||||||
|
async_result<T, Signature> target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename> class Associator,
|
||||||
|
typename T, typename CancellationSlot, typename DefaultCandidate>
|
||||||
|
struct associator<Associator,
|
||||||
|
cancellation_slot_binder<T, CancellationSlot>,
|
||||||
|
DefaultCandidate>
|
||||||
|
{
|
||||||
|
typedef typename Associator<T, DefaultCandidate>::type type;
|
||||||
|
|
||||||
|
static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
|
||||||
|
const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return Associator<T, DefaultCandidate>::get(b.get(), c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename CancellationSlot, typename CancellationSlot1>
|
||||||
|
struct associated_cancellation_slot<
|
||||||
|
cancellation_slot_binder<T, CancellationSlot>,
|
||||||
|
CancellationSlot1>
|
||||||
|
{
|
||||||
|
typedef CancellationSlot type;
|
||||||
|
|
||||||
|
static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
|
||||||
|
const CancellationSlot1& = CancellationSlot1()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return b.get_cancellation_slot();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BIND_CANCELLATION_SLOT_HPP
|
770
lib/asio/include/asio/bind_executor.hpp
Normal file
770
lib/asio/include/asio/bind_executor.hpp
Normal file
@ -0,0 +1,770 @@
|
|||||||
|
//
|
||||||
|
// bind_executor.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BIND_EXECUTOR_HPP
|
||||||
|
#define ASIO_BIND_EXECUTOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/detail/variadic_templates.hpp"
|
||||||
|
#include "asio/associated_executor.hpp"
|
||||||
|
#include "asio/associator.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
#include "asio/uses_executor.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef result_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct executor_binder_result_type
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef void result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct executor_binder_result_type<T,
|
||||||
|
typename void_type<typename T::result_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::result_type result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct executor_binder_result_type<R(*)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct executor_binder_result_type<R(&)()>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct executor_binder_result_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct executor_binder_result_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct executor_binder_result_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct executor_binder_result_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef R result_type;
|
||||||
|
protected:
|
||||||
|
typedef result_type result_type_or_void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedef argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct executor_binder_argument_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct executor_binder_argument_type<T,
|
||||||
|
typename void_type<typename T::argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::argument_type argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct executor_binder_argument_type<R(*)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct executor_binder_argument_type<R(&)(A1)>
|
||||||
|
{
|
||||||
|
typedef A1 argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to automatically define nested typedefs first_argument_type and
|
||||||
|
// second_argument_type.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct executor_binder_argument_types {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct executor_binder_argument_types<T,
|
||||||
|
typename void_type<typename T::first_argument_type>::type>
|
||||||
|
{
|
||||||
|
typedef typename T::first_argument_type first_argument_type;
|
||||||
|
typedef typename T::second_argument_type second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct executor_binder_argument_type<R(*)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct executor_binder_argument_type<R(&)(A1, A2)>
|
||||||
|
{
|
||||||
|
typedef A1 first_argument_type;
|
||||||
|
typedef A2 second_argument_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to perform uses_executor construction of the target type, if
|
||||||
|
// required.
|
||||||
|
|
||||||
|
template <typename T, typename Executor, bool UsesExecutor>
|
||||||
|
class executor_binder_base;
|
||||||
|
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
class executor_binder_base<T, Executor, true>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
template <typename E, typename U>
|
||||||
|
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
|
||||||
|
: executor_(ASIO_MOVE_CAST(E)(e)),
|
||||||
|
target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Executor executor_;
|
||||||
|
T target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
class executor_binder_base<T, Executor, false>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
template <typename E, typename U>
|
||||||
|
executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
|
||||||
|
: executor_(ASIO_MOVE_CAST(E)(e)),
|
||||||
|
target_(ASIO_MOVE_CAST(U)(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Executor executor_;
|
||||||
|
T target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to enable SFINAE on zero-argument operator() below.
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct executor_binder_result_of0
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct executor_binder_result_of0<T,
|
||||||
|
typename void_type<typename result_of<T()>::type>::type>
|
||||||
|
{
|
||||||
|
typedef typename result_of<T()>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// A call wrapper type to bind an executor of type @c Executor to an object of
|
||||||
|
/// type @c T.
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
class executor_binder
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
: public detail::executor_binder_result_type<T>,
|
||||||
|
public detail::executor_binder_argument_type<T>,
|
||||||
|
public detail::executor_binder_argument_types<T>,
|
||||||
|
private detail::executor_binder_base<
|
||||||
|
T, Executor, uses_executor<T, Executor>::value>
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the target object.
|
||||||
|
typedef T target_type;
|
||||||
|
|
||||||
|
/// The type of the associated executor.
|
||||||
|
typedef Executor executor_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The return type if a function.
|
||||||
|
/**
|
||||||
|
* The type of @c result_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to function type, @c result_type is a synonym for
|
||||||
|
* the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c result_type, then @c
|
||||||
|
* result_type is a synonym for @c T::result_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c result_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below result_type;
|
||||||
|
|
||||||
|
/// The type of the function's argument.
|
||||||
|
/**
|
||||||
|
* The type of @c argument_type is based on the type @c T of the wrapper's
|
||||||
|
* target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting a single argument,
|
||||||
|
* @c argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c argument_type, then @c
|
||||||
|
* argument_type is a synonym for @c T::argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's first argument.
|
||||||
|
/**
|
||||||
|
* The type of @c first_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* first_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c first_argument_type is a synonym for @c T::first_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c first_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below first_argument_type;
|
||||||
|
|
||||||
|
/// The type of the function's second argument.
|
||||||
|
/**
|
||||||
|
* The type of @c second_argument_type is based on the type @c T of the
|
||||||
|
* wrapper's target object:
|
||||||
|
*
|
||||||
|
* @li if @c T is a pointer to a function type accepting two arguments, @c
|
||||||
|
* second_argument_type is a synonym for the return type of @c T;
|
||||||
|
*
|
||||||
|
* @li if @c T is a class type with a member type @c first_argument_type,
|
||||||
|
* then @c second_argument_type is a synonym for @c T::second_argument_type;
|
||||||
|
*
|
||||||
|
* @li otherwise @c second_argument_type is not defined.
|
||||||
|
*/
|
||||||
|
typedef see_below second_argument_type;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Construct an executor wrapper for the specified object.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
executor_binder(executor_arg_t, const executor_type& e,
|
||||||
|
ASIO_MOVE_ARG(U) u)
|
||||||
|
: base_type(e, ASIO_MOVE_CAST(U)(u))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy constructor.
|
||||||
|
executor_binder(const executor_binder& other)
|
||||||
|
: base_type(other.get_executor(), other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy, but specify a different executor.
|
||||||
|
executor_binder(executor_arg_t, const executor_type& e,
|
||||||
|
const executor_binder& other)
|
||||||
|
: base_type(e, other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different executor wrapper type.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the @c Executor type is constructible
|
||||||
|
* from type @c OtherExecutor, and the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherExecutor>
|
||||||
|
executor_binder(const executor_binder<U, OtherExecutor>& other)
|
||||||
|
: base_type(other.get_executor(), other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a copy of a different executor wrapper type, but specify a
|
||||||
|
/// different executor.
|
||||||
|
/**
|
||||||
|
* This constructor is only valid if the type @c T is constructible from type
|
||||||
|
* @c U.
|
||||||
|
*/
|
||||||
|
template <typename U, typename OtherExecutor>
|
||||||
|
executor_binder(executor_arg_t, const executor_type& e,
|
||||||
|
const executor_binder<U, OtherExecutor>& other)
|
||||||
|
: base_type(e, other.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Move constructor.
|
||||||
|
executor_binder(executor_binder&& other)
|
||||||
|
: base_type(ASIO_MOVE_CAST(executor_type)(other.get_executor()),
|
||||||
|
ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct the target object, but specify a different executor.
|
||||||
|
executor_binder(executor_arg_t, const executor_type& e,
|
||||||
|
executor_binder&& other)
|
||||||
|
: base_type(e, ASIO_MOVE_CAST(T)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different executor wrapper type.
|
||||||
|
template <typename U, typename OtherExecutor>
|
||||||
|
executor_binder(executor_binder<U, OtherExecutor>&& other)
|
||||||
|
: base_type(ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()),
|
||||||
|
ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move construct from a different executor wrapper type, but specify a
|
||||||
|
/// different executor.
|
||||||
|
template <typename U, typename OtherExecutor>
|
||||||
|
executor_binder(executor_arg_t, const executor_type& e,
|
||||||
|
executor_binder<U, OtherExecutor>&& other)
|
||||||
|
: base_type(e, ASIO_MOVE_CAST(U)(other.get()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
~executor_binder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
target_type& get() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return this->target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a reference to the target object.
|
||||||
|
const target_type& get() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return this->target_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain the associated executor.
|
||||||
|
executor_type get_executor() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return this->executor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <typename... Args> auto operator()(Args&& ...);
|
||||||
|
template <typename... Args> auto operator()(Args&& ...) const;
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return this->target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forwarding function call operator.
|
||||||
|
template <typename... Args>
|
||||||
|
typename result_of<T(Args...)>::type operator()(
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
return this->target_(ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typename detail::executor_binder_result_of0<T>::type operator()()
|
||||||
|
{
|
||||||
|
return this->target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename detail::executor_binder_result_of0<T>::type operator()() const
|
||||||
|
{
|
||||||
|
return this->target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
typedef typename detail::executor_binder_result_type<T>::result_type_or_void
|
||||||
|
result_type_or_void;
|
||||||
|
|
||||||
|
result_type_or_void operator()()
|
||||||
|
{
|
||||||
|
return this->target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type_or_void operator()() const
|
||||||
|
{
|
||||||
|
return this->target_();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
result_type_or_void operator()( \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
|
||||||
|
#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef detail::executor_binder_base<T, Executor,
|
||||||
|
uses_executor<T, Executor>::value> base_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Associate an object of type @c T with an executor of type @c Executor.
|
||||||
|
template <typename Executor, typename T>
|
||||||
|
ASIO_NODISCARD inline executor_binder<typename decay<T>::type, Executor>
|
||||||
|
bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
{
|
||||||
|
return executor_binder<typename decay<T>::type, Executor>(
|
||||||
|
executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Associate an object of type @c T with an execution context's executor.
|
||||||
|
template <typename ExecutionContext, typename T>
|
||||||
|
ASIO_NODISCARD inline executor_binder<typename decay<T>::type,
|
||||||
|
typename ExecutionContext::executor_type>
|
||||||
|
bind_executor(ExecutionContext& ctx, ASIO_MOVE_ARG(T) t,
|
||||||
|
typename constraint<is_convertible<
|
||||||
|
ExecutionContext&, execution_context&>::value>::type = 0)
|
||||||
|
{
|
||||||
|
return executor_binder<typename decay<T>::type,
|
||||||
|
typename ExecutionContext::executor_type>(
|
||||||
|
executor_arg_t(), ctx.get_executor(), ASIO_MOVE_CAST(T)(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
struct uses_executor<executor_binder<T, Executor>, Executor>
|
||||||
|
: true_type {};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename Executor, typename = void>
|
||||||
|
class executor_binder_completion_handler_async_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
explicit executor_binder_completion_handler_async_result(T&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename Executor>
|
||||||
|
class executor_binder_completion_handler_async_result<
|
||||||
|
TargetAsyncResult, Executor,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::completion_handler_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef executor_binder<
|
||||||
|
typename TargetAsyncResult::completion_handler_type, Executor>
|
||||||
|
completion_handler_type;
|
||||||
|
|
||||||
|
explicit executor_binder_completion_handler_async_result(
|
||||||
|
typename TargetAsyncResult::completion_handler_type& handler)
|
||||||
|
: target_(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typename TargetAsyncResult::return_type get()
|
||||||
|
{
|
||||||
|
return target_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TargetAsyncResult target_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult, typename = void>
|
||||||
|
struct executor_binder_async_result_return_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TargetAsyncResult>
|
||||||
|
struct executor_binder_async_result_return_type<
|
||||||
|
TargetAsyncResult,
|
||||||
|
typename void_type<
|
||||||
|
typename TargetAsyncResult::return_type
|
||||||
|
>::type>
|
||||||
|
{
|
||||||
|
typedef typename TargetAsyncResult::return_type return_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename Executor, typename Signature>
|
||||||
|
class async_result<executor_binder<T, Executor>, Signature> :
|
||||||
|
public detail::executor_binder_completion_handler_async_result<
|
||||||
|
async_result<T, Signature>, Executor>,
|
||||||
|
public detail::executor_binder_async_result_return_type<
|
||||||
|
async_result<T, Signature> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit async_result(executor_binder<T, Executor>& b)
|
||||||
|
: detail::executor_binder_completion_handler_async_result<
|
||||||
|
async_result<T, Signature>, Executor>(b.get())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Initiation>
|
||||||
|
struct init_wrapper
|
||||||
|
{
|
||||||
|
template <typename Init>
|
||||||
|
init_wrapper(const Executor& ex, ASIO_MOVE_ARG(Init) init)
|
||||||
|
: ex_(ex),
|
||||||
|
initiation_(ASIO_MOVE_CAST(Init)(init))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>(
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler, typename... Args>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler,
|
||||||
|
ASIO_MOVE_ARG(Args)... args) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>(
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),
|
||||||
|
ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler)
|
||||||
|
{
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)(
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>(
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
void operator()(
|
||||||
|
ASIO_MOVE_ARG(Handler) handler) const
|
||||||
|
{
|
||||||
|
initiation_(
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>(
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
ASIO_MOVE_CAST(Initiation)(initiation_)( \
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>( \
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
void operator()( \
|
||||||
|
ASIO_MOVE_ARG(Handler) handler, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) const \
|
||||||
|
{ \
|
||||||
|
initiation_( \
|
||||||
|
executor_binder<typename decay<Handler>::type, Executor>( \
|
||||||
|
executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \
|
||||||
|
ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INIT_WRAPPER_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
Executor ex_;
|
||||||
|
Initiation initiation_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken, typename... Args>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get(),
|
||||||
|
declval<ASIO_MOVE_ARG(Args)>()...)))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token,
|
||||||
|
ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get(), ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
template <typename Initiation, typename RawCompletionToken>
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
|
||||||
|
(async_initiate<T, Signature>(
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||||
|
declval<RawCompletionToken>().get())))
|
||||||
|
initiate(
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation,
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token)
|
||||||
|
{
|
||||||
|
return async_initiate<T, Signature>(
|
||||||
|
init_wrapper<typename decay<Initiation>::type>(
|
||||||
|
token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),
|
||||||
|
token.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_INITIATE_DEF(n) \
|
||||||
|
template <typename Initiation, typename RawCompletionToken, \
|
||||||
|
ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
|
||||||
|
(async_initiate<T, Signature>( \
|
||||||
|
declval<init_wrapper<typename decay<Initiation>::type> >(), \
|
||||||
|
declval<RawCompletionToken>().get(), \
|
||||||
|
ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
|
||||||
|
initiate( \
|
||||||
|
ASIO_MOVE_ARG(Initiation) initiation, \
|
||||||
|
ASIO_MOVE_ARG(RawCompletionToken) token, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
return async_initiate<T, Signature>( \
|
||||||
|
init_wrapper<typename decay<Initiation>::type>( \
|
||||||
|
token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), \
|
||||||
|
token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
|
||||||
|
#undef ASIO_PRIVATE_INITIATE_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
private:
|
||||||
|
async_result(const async_result&) ASIO_DELETED;
|
||||||
|
async_result& operator=(const async_result&) ASIO_DELETED;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename> class Associator,
|
||||||
|
typename T, typename Executor, typename DefaultCandidate>
|
||||||
|
struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>
|
||||||
|
{
|
||||||
|
typedef typename Associator<T, DefaultCandidate>::type type;
|
||||||
|
|
||||||
|
static type get(const executor_binder<T, Executor>& b,
|
||||||
|
const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return Associator<T, DefaultCandidate>::get(b.get(), c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Executor, typename Executor1>
|
||||||
|
struct associated_executor<executor_binder<T, Executor>, Executor1>
|
||||||
|
{
|
||||||
|
typedef Executor type;
|
||||||
|
|
||||||
|
static type get(const executor_binder<T, Executor>& b,
|
||||||
|
const Executor1& = Executor1()) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return b.get_executor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BIND_EXECUTOR_HPP
|
2514
lib/asio/include/asio/buffer.hpp
Normal file
2514
lib/asio/include/asio/buffer.hpp
Normal file
File diff suppressed because it is too large
Load Diff
328
lib/asio/include/asio/buffer_registration.hpp
Normal file
328
lib/asio/include/asio/buffer_registration.hpp
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
//
|
||||||
|
// buffer_registration.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFER_REGISTRATION_HPP
|
||||||
|
#define ASIO_BUFFER_REGISTRATION_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include "asio/detail/memory.hpp"
|
||||||
|
#include "asio/execution/context.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
#include "asio/query.hpp"
|
||||||
|
#include "asio/registered_buffer.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
# include "asio/detail/scheduler.hpp"
|
||||||
|
# include "asio/detail/io_uring_service.hpp"
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE)
|
||||||
|
# include <utility>
|
||||||
|
#endif // defined(ASIO_HAS_MOVE)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class buffer_registration_base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static mutable_registered_buffer make_buffer(const mutable_buffer& b,
|
||||||
|
const void* scope, int index) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return mutable_registered_buffer(b, registered_buffer_id(scope, index));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Automatically registers and unregistered buffers with an execution context.
|
||||||
|
/**
|
||||||
|
* For portability, applications should assume that only one registration is
|
||||||
|
* permitted per execution context.
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
typename Allocator = std::allocator<void> >
|
||||||
|
class buffer_registration
|
||||||
|
: detail::buffer_registration_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The allocator type used for allocating storage for the buffers container.
|
||||||
|
typedef Allocator allocator_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The type of an iterator over the registered buffers.
|
||||||
|
typedef unspecified iterator;
|
||||||
|
|
||||||
|
/// The type of a const iterator over the registered buffers.
|
||||||
|
typedef unspecified const_iterator;
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef std::vector<mutable_registered_buffer>::const_iterator iterator;
|
||||||
|
typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Register buffers with an executor's execution context.
|
||||||
|
template <typename Executor>
|
||||||
|
buffer_registration(const Executor& ex,
|
||||||
|
const MutableBufferSequence& buffer_sequence,
|
||||||
|
const allocator_type& alloc = allocator_type(),
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
: buffer_sequence_(buffer_sequence),
|
||||||
|
buffers_(
|
||||||
|
ASIO_REBIND_ALLOC(allocator_type,
|
||||||
|
mutable_registered_buffer)(alloc))
|
||||||
|
{
|
||||||
|
init_buffers(buffer_registration::get_context(ex),
|
||||||
|
asio::buffer_sequence_begin(buffer_sequence_),
|
||||||
|
asio::buffer_sequence_end(buffer_sequence_));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register buffers with an execution context.
|
||||||
|
template <typename ExecutionContext>
|
||||||
|
buffer_registration(ExecutionContext& ctx,
|
||||||
|
const MutableBufferSequence& buffer_sequence,
|
||||||
|
const allocator_type& alloc = allocator_type(),
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
: buffer_sequence_(buffer_sequence),
|
||||||
|
buffers_(
|
||||||
|
ASIO_REBIND_ALLOC(allocator_type,
|
||||||
|
mutable_registered_buffer)(alloc))
|
||||||
|
{
|
||||||
|
init_buffers(ctx,
|
||||||
|
asio::buffer_sequence_begin(buffer_sequence_),
|
||||||
|
asio::buffer_sequence_end(buffer_sequence_));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move constructor.
|
||||||
|
buffer_registration(buffer_registration&& other) ASIO_NOEXCEPT
|
||||||
|
: buffer_sequence_(std::move(other.buffer_sequence_)),
|
||||||
|
buffers_(std::move(other.buffers_))
|
||||||
|
{
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
service_ = other.service_;
|
||||||
|
other.service_ = 0;
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Unregisters the buffers.
|
||||||
|
~buffer_registration()
|
||||||
|
{
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
if (service_)
|
||||||
|
service_->unregister_buffers();
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Move assignment.
|
||||||
|
buffer_registration& operator=(
|
||||||
|
buffer_registration&& other) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
buffer_sequence_ = std::move(other.buffer_sequence_);
|
||||||
|
buffers_ = std::move(other.buffers_);
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
if (service_)
|
||||||
|
service_->unregister_buffers();
|
||||||
|
service_ = other.service_;
|
||||||
|
other.service_ = 0;
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Get the number of registered buffers.
|
||||||
|
std::size_t size() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the begin iterator for the sequence of registered buffers.
|
||||||
|
const_iterator begin() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the begin iterator for the sequence of registered buffers.
|
||||||
|
const_iterator cbegin() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the end iterator for the sequence of registered buffers.
|
||||||
|
const_iterator end() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the end iterator for the sequence of registered buffers.
|
||||||
|
const_iterator cend() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the buffer at the specified index.
|
||||||
|
const mutable_registered_buffer& operator[](std::size_t i) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the buffer at the specified index.
|
||||||
|
const mutable_registered_buffer& at(std::size_t i) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return buffers_.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Disallow copying and assignment.
|
||||||
|
buffer_registration(const buffer_registration&) ASIO_DELETED;
|
||||||
|
buffer_registration& operator=(const buffer_registration&) ASIO_DELETED;
|
||||||
|
|
||||||
|
// Helper function to get an executor's context.
|
||||||
|
template <typename T>
|
||||||
|
static execution_context& get_context(const T& t,
|
||||||
|
typename enable_if<execution::is_executor<T>::value>::type* = 0)
|
||||||
|
{
|
||||||
|
return asio::query(t, execution::context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get an executor's context.
|
||||||
|
template <typename T>
|
||||||
|
static execution_context& get_context(const T& t,
|
||||||
|
typename enable_if<!execution::is_executor<T>::value>::type* = 0)
|
||||||
|
{
|
||||||
|
return t.context();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to initialise the container of buffers.
|
||||||
|
template <typename Iterator>
|
||||||
|
void init_buffers(execution_context& ctx, Iterator begin, Iterator end)
|
||||||
|
{
|
||||||
|
std::size_t n = std::distance(begin, end);
|
||||||
|
buffers_.resize(n);
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
service_ = &use_service<detail::io_uring_service>(ctx);
|
||||||
|
std::vector<iovec,
|
||||||
|
ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n,
|
||||||
|
ASIO_REBIND_ALLOC(allocator_type, iovec)(
|
||||||
|
buffers_.get_allocator()));
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
|
||||||
|
Iterator iter = begin;
|
||||||
|
for (int index = 0; iter != end; ++index, ++iter)
|
||||||
|
{
|
||||||
|
mutable_buffer b(*iter);
|
||||||
|
std::size_t i = static_cast<std::size_t>(index);
|
||||||
|
buffers_[i] = this->make_buffer(b, &ctx, index);
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
iovecs[i].iov_base = buffers_[i].data();
|
||||||
|
iovecs[i].iov_len = buffers_[i].size();
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
service_->register_buffers(&iovecs[0],
|
||||||
|
static_cast<unsigned>(iovecs.size()));
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableBufferSequence buffer_sequence_;
|
||||||
|
std::vector<mutable_registered_buffer,
|
||||||
|
ASIO_REBIND_ALLOC(allocator_type,
|
||||||
|
mutable_registered_buffer)> buffers_;
|
||||||
|
#if defined(ASIO_HAS_IO_URING)
|
||||||
|
detail::io_uring_service* service_;
|
||||||
|
#endif // defined(ASIO_HAS_IO_URING)
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Register buffers with an execution context.
|
||||||
|
template <typename Executor, typename MutableBufferSequence>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
buffer_registration<MutableBufferSequence>
|
||||||
|
register_buffers(const Executor& ex,
|
||||||
|
const MutableBufferSequence& buffer_sequence,
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
{
|
||||||
|
return buffer_registration<MutableBufferSequence>(ex, buffer_sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register buffers with an execution context.
|
||||||
|
template <typename Executor, typename MutableBufferSequence, typename Allocator>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
buffer_registration<MutableBufferSequence, Allocator>
|
||||||
|
register_buffers(const Executor& ex,
|
||||||
|
const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0)
|
||||||
|
{
|
||||||
|
return buffer_registration<MutableBufferSequence, Allocator>(
|
||||||
|
ex, buffer_sequence, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register buffers with an execution context.
|
||||||
|
template <typename ExecutionContext, typename MutableBufferSequence>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
buffer_registration<MutableBufferSequence>
|
||||||
|
register_buffers(ExecutionContext& ctx,
|
||||||
|
const MutableBufferSequence& buffer_sequence,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
{
|
||||||
|
return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register buffers with an execution context.
|
||||||
|
template <typename ExecutionContext,
|
||||||
|
typename MutableBufferSequence, typename Allocator>
|
||||||
|
ASIO_NODISCARD inline
|
||||||
|
buffer_registration<MutableBufferSequence, Allocator>
|
||||||
|
register_buffers(ExecutionContext& ctx,
|
||||||
|
const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0)
|
||||||
|
{
|
||||||
|
return buffer_registration<MutableBufferSequence, Allocator>(
|
||||||
|
ctx, buffer_sequence, alloc);
|
||||||
|
}
|
||||||
|
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFER_REGISTRATION_HPP
|
265
lib/asio/include/asio/buffered_read_stream.hpp
Normal file
265
lib/asio/include/asio/buffered_read_stream.hpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
//
|
||||||
|
// buffered_read_stream.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_READ_STREAM_HPP
|
||||||
|
#define ASIO_BUFFERED_READ_STREAM_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/buffered_read_stream_fwd.hpp"
|
||||||
|
#include "asio/buffer.hpp"
|
||||||
|
#include "asio/detail/bind_handler.hpp"
|
||||||
|
#include "asio/detail/buffer_resize_guard.hpp"
|
||||||
|
#include "asio/detail/buffered_stream_storage.hpp"
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Adds buffering to the read-related operations of a stream.
|
||||||
|
/**
|
||||||
|
* The buffered_read_stream class template can be used to add buffering to the
|
||||||
|
* synchronous and asynchronous read operations of a stream.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Concepts:
|
||||||
|
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_read_stream
|
||||||
|
: private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the next layer.
|
||||||
|
typedef typename remove_reference<Stream>::type next_layer_type;
|
||||||
|
|
||||||
|
/// The type of the lowest layer.
|
||||||
|
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
|
||||||
|
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef typename lowest_layer_type::executor_type executor_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The default buffer size.
|
||||||
|
static const std::size_t default_buffer_size = implementation_defined;
|
||||||
|
#else
|
||||||
|
ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
explicit buffered_read_stream(Arg& a)
|
||||||
|
: next_layer_(a),
|
||||||
|
storage_(default_buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
buffered_read_stream(Arg& a, std::size_t buffer_size)
|
||||||
|
: next_layer_(a),
|
||||||
|
storage_(buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the next layer.
|
||||||
|
next_layer_type& next_layer()
|
||||||
|
{
|
||||||
|
return next_layer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer().get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
next_layer_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
next_layer_.close(ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return next_layer_.write_some(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written,
|
||||||
|
/// or 0 if an error occurred.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return next_layer_.write_some(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write. The data being written must be valid for the
|
||||||
|
/// lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return next_layer_.async_write_some(buffers,
|
||||||
|
ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||||
|
/// buffer as a result of the operation. Throws an exception on failure.
|
||||||
|
std::size_t fill();
|
||||||
|
|
||||||
|
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||||
|
/// buffer as a result of the operation, or 0 if an error occurred.
|
||||||
|
std::size_t fill(asio::error_code& ec);
|
||||||
|
|
||||||
|
/// Start an asynchronous fill.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_fill(
|
||||||
|
ASIO_MOVE_ARG(ReadHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read. Throws
|
||||||
|
/// an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers);
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read or 0 if
|
||||||
|
/// an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec);
|
||||||
|
|
||||||
|
/// Start an asynchronous read. The buffer into which the data will be read
|
||||||
|
/// must be valid for the lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers);
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read,
|
||||||
|
/// or 0 if an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec);
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail()
|
||||||
|
{
|
||||||
|
return storage_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
ec = asio::error_code();
|
||||||
|
return storage_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Copy data out of the internal buffer to the specified target buffer.
|
||||||
|
/// Returns the number of bytes copied.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t copy(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
std::size_t bytes_copied = asio::buffer_copy(
|
||||||
|
buffers, storage_.data(), storage_.size());
|
||||||
|
storage_.consume(bytes_copied);
|
||||||
|
return bytes_copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy data from the internal buffer to the specified target buffer, without
|
||||||
|
/// removing the data from the internal buffer. Returns the number of bytes
|
||||||
|
/// copied.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek_copy(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return asio::buffer_copy(buffers, storage_.data(), storage_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The next layer.
|
||||||
|
Stream next_layer_;
|
||||||
|
|
||||||
|
// The data in the buffer.
|
||||||
|
detail::buffered_stream_storage storage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/buffered_read_stream.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_READ_STREAM_HPP
|
25
lib/asio/include/asio/buffered_read_stream_fwd.hpp
Normal file
25
lib/asio/include/asio/buffered_read_stream_fwd.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// buffered_read_stream_fwd.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_READ_STREAM_FWD_HPP
|
||||||
|
#define ASIO_BUFFERED_READ_STREAM_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_read_stream;
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP
|
295
lib/asio/include/asio/buffered_stream.hpp
Normal file
295
lib/asio/include/asio/buffered_stream.hpp
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
//
|
||||||
|
// buffered_stream.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_STREAM_HPP
|
||||||
|
#define ASIO_BUFFERED_STREAM_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/buffered_read_stream.hpp"
|
||||||
|
#include "asio/buffered_write_stream.hpp"
|
||||||
|
#include "asio/buffered_stream_fwd.hpp"
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Adds buffering to the read- and write-related operations of a stream.
|
||||||
|
/**
|
||||||
|
* The buffered_stream class template can be used to add buffering to the
|
||||||
|
* synchronous and asynchronous read and write operations of a stream.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Concepts:
|
||||||
|
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_stream
|
||||||
|
: private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the next layer.
|
||||||
|
typedef typename remove_reference<Stream>::type next_layer_type;
|
||||||
|
|
||||||
|
/// The type of the lowest layer.
|
||||||
|
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
|
||||||
|
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef typename lowest_layer_type::executor_type executor_type;
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
explicit buffered_stream(Arg& a)
|
||||||
|
: inner_stream_impl_(a),
|
||||||
|
stream_impl_(inner_stream_impl_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
explicit buffered_stream(Arg& a, std::size_t read_buffer_size,
|
||||||
|
std::size_t write_buffer_size)
|
||||||
|
: inner_stream_impl_(a, write_buffer_size),
|
||||||
|
stream_impl_(inner_stream_impl_, read_buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the next layer.
|
||||||
|
next_layer_type& next_layer()
|
||||||
|
{
|
||||||
|
return stream_impl_.next_layer().next_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return stream_impl_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return stream_impl_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return stream_impl_.lowest_layer().get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
stream_impl_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
stream_impl_.close(ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush all data from the buffer to the next layer. Returns the number of
|
||||||
|
/// bytes written to the next layer on the last write operation. Throws an
|
||||||
|
/// exception on failure.
|
||||||
|
std::size_t flush()
|
||||||
|
{
|
||||||
|
return stream_impl_.next_layer().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush all data from the buffer to the next layer. Returns the number of
|
||||||
|
/// bytes written to the next layer on the last write operation, or 0 if an
|
||||||
|
/// error occurred.
|
||||||
|
std::size_t flush(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.next_layer().flush(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous flush.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_flush(
|
||||||
|
ASIO_MOVE_ARG(WriteHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return stream_impl_.next_layer().async_flush(
|
||||||
|
ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return stream_impl_.write_some(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written,
|
||||||
|
/// or 0 if an error occurred.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.write_some(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous write. The data being written must be valid for the
|
||||||
|
/// lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return stream_impl_.async_write_some(buffers,
|
||||||
|
ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||||
|
/// buffer as a result of the operation. Throws an exception on failure.
|
||||||
|
std::size_t fill()
|
||||||
|
{
|
||||||
|
return stream_impl_.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill the buffer with some data. Returns the number of bytes placed in the
|
||||||
|
/// buffer as a result of the operation, or 0 if an error occurred.
|
||||||
|
std::size_t fill(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.fill(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous fill.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_fill(
|
||||||
|
ASIO_MOVE_ARG(ReadHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return stream_impl_.async_fill(ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read. Throws
|
||||||
|
/// an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return stream_impl_.read_some(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read or 0 if
|
||||||
|
/// an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.read_some(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read. The buffer into which the data will be read
|
||||||
|
/// must be valid for the lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return stream_impl_.async_read_some(buffers,
|
||||||
|
ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return stream_impl_.peek(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read,
|
||||||
|
/// or 0 if an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.peek(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail()
|
||||||
|
{
|
||||||
|
return stream_impl_.in_avail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return stream_impl_.in_avail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The buffered write stream.
|
||||||
|
typedef buffered_write_stream<Stream> write_stream_type;
|
||||||
|
write_stream_type inner_stream_impl_;
|
||||||
|
|
||||||
|
// The buffered read stream.
|
||||||
|
typedef buffered_read_stream<write_stream_type&> read_stream_type;
|
||||||
|
read_stream_type stream_impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_STREAM_HPP
|
25
lib/asio/include/asio/buffered_stream_fwd.hpp
Normal file
25
lib/asio/include/asio/buffered_stream_fwd.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// buffered_stream_fwd.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_STREAM_FWD_HPP
|
||||||
|
#define ASIO_BUFFERED_STREAM_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_stream;
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_STREAM_FWD_HPP
|
257
lib/asio/include/asio/buffered_write_stream.hpp
Normal file
257
lib/asio/include/asio/buffered_write_stream.hpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
//
|
||||||
|
// buffered_write_stream.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_WRITE_STREAM_HPP
|
||||||
|
#define ASIO_BUFFERED_WRITE_STREAM_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include "asio/buffered_write_stream_fwd.hpp"
|
||||||
|
#include "asio/buffer.hpp"
|
||||||
|
#include "asio/completion_condition.hpp"
|
||||||
|
#include "asio/detail/bind_handler.hpp"
|
||||||
|
#include "asio/detail/buffered_stream_storage.hpp"
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/write.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Adds buffering to the write-related operations of a stream.
|
||||||
|
/**
|
||||||
|
* The buffered_write_stream class template can be used to add buffering to the
|
||||||
|
* synchronous and asynchronous write operations of a stream.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*
|
||||||
|
* @par Concepts:
|
||||||
|
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_write_stream
|
||||||
|
: private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the next layer.
|
||||||
|
typedef typename remove_reference<Stream>::type next_layer_type;
|
||||||
|
|
||||||
|
/// The type of the lowest layer.
|
||||||
|
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
|
||||||
|
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
typedef typename lowest_layer_type::executor_type executor_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The default buffer size.
|
||||||
|
static const std::size_t default_buffer_size = implementation_defined;
|
||||||
|
#else
|
||||||
|
ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
explicit buffered_write_stream(Arg& a)
|
||||||
|
: next_layer_(a),
|
||||||
|
storage_(default_buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct, passing the specified argument to initialise the next layer.
|
||||||
|
template <typename Arg>
|
||||||
|
buffered_write_stream(Arg& a, std::size_t buffer_size)
|
||||||
|
: next_layer_(a),
|
||||||
|
storage_(buffer_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the next layer.
|
||||||
|
next_layer_type& next_layer()
|
||||||
|
{
|
||||||
|
return next_layer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the lowest layer.
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a const reference to the lowest layer.
|
||||||
|
const lowest_layer_type& lowest_layer() const
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the executor associated with the object.
|
||||||
|
executor_type get_executor() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return next_layer_.lowest_layer().get_executor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
next_layer_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the stream.
|
||||||
|
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
next_layer_.close(ec);
|
||||||
|
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush all data from the buffer to the next layer. Returns the number of
|
||||||
|
/// bytes written to the next layer on the last write operation. Throws an
|
||||||
|
/// exception on failure.
|
||||||
|
std::size_t flush();
|
||||||
|
|
||||||
|
/// Flush all data from the buffer to the next layer. Returns the number of
|
||||||
|
/// bytes written to the next layer on the last write operation, or 0 if an
|
||||||
|
/// error occurred.
|
||||||
|
std::size_t flush(asio::error_code& ec);
|
||||||
|
|
||||||
|
/// Start an asynchronous flush.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_flush(
|
||||||
|
ASIO_MOVE_ARG(WriteHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers);
|
||||||
|
|
||||||
|
/// Write the given data to the stream. Returns the number of bytes written,
|
||||||
|
/// or 0 if an error occurred and the error handler did not throw.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||||
|
asio::error_code& ec);
|
||||||
|
|
||||||
|
/// Start an asynchronous write. The data being written must be valid for the
|
||||||
|
/// lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename ConstBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) WriteHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_write_some(const ConstBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(WriteHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read. Throws
|
||||||
|
/// an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return next_layer_.read_some(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read some data from the stream. Returns the number of bytes read or 0 if
|
||||||
|
/// an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return next_layer_.read_some(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start an asynchronous read. The buffer into which the data will be read
|
||||||
|
/// must be valid for the lifetime of the asynchronous operation.
|
||||||
|
/**
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(asio::error_code, std::size_t) @endcode
|
||||||
|
*/
|
||||||
|
template <typename MutableBufferSequence,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
|
||||||
|
std::size_t)) ReadHandler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
|
||||||
|
void (asio::error_code, std::size_t))
|
||||||
|
async_read_some(const MutableBufferSequence& buffers,
|
||||||
|
ASIO_MOVE_ARG(ReadHandler) handler
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
|
||||||
|
{
|
||||||
|
return next_layer_.async_read_some(buffers,
|
||||||
|
ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read.
|
||||||
|
/// Throws an exception on failure.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return next_layer_.peek(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peek at the incoming data on the stream. Returns the number of bytes read,
|
||||||
|
/// or 0 if an error occurred.
|
||||||
|
template <typename MutableBufferSequence>
|
||||||
|
std::size_t peek(const MutableBufferSequence& buffers,
|
||||||
|
asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return next_layer_.peek(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail()
|
||||||
|
{
|
||||||
|
return next_layer_.in_avail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine the amount of data that may be read without blocking.
|
||||||
|
std::size_t in_avail(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return next_layer_.in_avail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Copy data into the internal buffer from the specified source buffer.
|
||||||
|
/// Returns the number of bytes copied.
|
||||||
|
template <typename ConstBufferSequence>
|
||||||
|
std::size_t copy(const ConstBufferSequence& buffers);
|
||||||
|
|
||||||
|
/// The next layer.
|
||||||
|
Stream next_layer_;
|
||||||
|
|
||||||
|
// The data in the buffer.
|
||||||
|
detail::buffered_stream_storage storage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/buffered_write_stream.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_WRITE_STREAM_HPP
|
25
lib/asio/include/asio/buffered_write_stream_fwd.hpp
Normal file
25
lib/asio/include/asio/buffered_write_stream_fwd.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// buffered_write_stream_fwd.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
|
||||||
|
#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
class buffered_write_stream;
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
|
521
lib/asio/include/asio/buffers_iterator.hpp
Normal file
521
lib/asio/include/asio/buffers_iterator.hpp
Normal file
@ -0,0 +1,521 @@
|
|||||||
|
//
|
||||||
|
// buffers_iterator.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BUFFERS_ITERATOR_HPP
|
||||||
|
#define ASIO_BUFFERS_ITERATOR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
#include "asio/buffer.hpp"
|
||||||
|
#include "asio/detail/assert.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <bool IsMutable>
|
||||||
|
struct buffers_iterator_types_helper;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct buffers_iterator_types_helper<false>
|
||||||
|
{
|
||||||
|
typedef const_buffer buffer_type;
|
||||||
|
template <typename ByteType>
|
||||||
|
struct byte_type
|
||||||
|
{
|
||||||
|
typedef typename add_const<ByteType>::type type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct buffers_iterator_types_helper<true>
|
||||||
|
{
|
||||||
|
typedef mutable_buffer buffer_type;
|
||||||
|
template <typename ByteType>
|
||||||
|
struct byte_type
|
||||||
|
{
|
||||||
|
typedef ByteType type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename BufferSequence, typename ByteType>
|
||||||
|
struct buffers_iterator_types
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
is_mutable = is_convertible<
|
||||||
|
typename BufferSequence::value_type,
|
||||||
|
mutable_buffer>::value
|
||||||
|
};
|
||||||
|
typedef buffers_iterator_types_helper<is_mutable> helper;
|
||||||
|
typedef typename helper::buffer_type buffer_type;
|
||||||
|
typedef typename helper::template byte_type<ByteType>::type byte_type;
|
||||||
|
typedef typename BufferSequence::const_iterator const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ByteType>
|
||||||
|
struct buffers_iterator_types<mutable_buffer, ByteType>
|
||||||
|
{
|
||||||
|
typedef mutable_buffer buffer_type;
|
||||||
|
typedef ByteType byte_type;
|
||||||
|
typedef const mutable_buffer* const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ByteType>
|
||||||
|
struct buffers_iterator_types<const_buffer, ByteType>
|
||||||
|
{
|
||||||
|
typedef const_buffer buffer_type;
|
||||||
|
typedef typename add_const<ByteType>::type byte_type;
|
||||||
|
typedef const const_buffer* const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
template <typename ByteType>
|
||||||
|
struct buffers_iterator_types<mutable_buffers_1, ByteType>
|
||||||
|
{
|
||||||
|
typedef mutable_buffer buffer_type;
|
||||||
|
typedef ByteType byte_type;
|
||||||
|
typedef const mutable_buffer* const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ByteType>
|
||||||
|
struct buffers_iterator_types<const_buffers_1, ByteType>
|
||||||
|
{
|
||||||
|
typedef const_buffer buffer_type;
|
||||||
|
typedef typename add_const<ByteType>::type byte_type;
|
||||||
|
typedef const const_buffer* const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A random access iterator over the bytes in a buffer sequence.
|
||||||
|
template <typename BufferSequence, typename ByteType = char>
|
||||||
|
class buffers_iterator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename detail::buffers_iterator_types<
|
||||||
|
BufferSequence, ByteType>::buffer_type buffer_type;
|
||||||
|
|
||||||
|
typedef typename detail::buffers_iterator_types<BufferSequence,
|
||||||
|
ByteType>::const_iterator buffer_sequence_iterator_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The type used for the distance between two iterators.
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
|
||||||
|
/// The type of the value pointed to by the iterator.
|
||||||
|
typedef ByteType value_type;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The type of the result of applying operator->() to the iterator.
|
||||||
|
/**
|
||||||
|
* If the buffer sequence stores buffer objects that are convertible to
|
||||||
|
* mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
|
||||||
|
* pointer to a const ByteType.
|
||||||
|
*/
|
||||||
|
typedef const_or_non_const_ByteType* pointer;
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef typename detail::buffers_iterator_types<
|
||||||
|
BufferSequence, ByteType>::byte_type* pointer;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// The type of the result of applying operator*() to the iterator.
|
||||||
|
/**
|
||||||
|
* If the buffer sequence stores buffer objects that are convertible to
|
||||||
|
* mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
|
||||||
|
* reference to a const ByteType.
|
||||||
|
*/
|
||||||
|
typedef const_or_non_const_ByteType& reference;
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef typename detail::buffers_iterator_types<
|
||||||
|
BufferSequence, ByteType>::byte_type& reference;
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// The iterator category.
|
||||||
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
/// Default constructor. Creates an iterator in an undefined state.
|
||||||
|
buffers_iterator()
|
||||||
|
: current_buffer_(),
|
||||||
|
current_buffer_position_(0),
|
||||||
|
begin_(),
|
||||||
|
current_(),
|
||||||
|
end_(),
|
||||||
|
position_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct an iterator representing the beginning of the buffers' data.
|
||||||
|
static buffers_iterator begin(const BufferSequence& buffers)
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
||||||
|
__attribute__ ((__noinline__))
|
||||||
|
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
||||||
|
{
|
||||||
|
buffers_iterator new_iter;
|
||||||
|
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
|
||||||
|
new_iter.current_ = asio::buffer_sequence_begin(buffers);
|
||||||
|
new_iter.end_ = asio::buffer_sequence_end(buffers);
|
||||||
|
while (new_iter.current_ != new_iter.end_)
|
||||||
|
{
|
||||||
|
new_iter.current_buffer_ = *new_iter.current_;
|
||||||
|
if (new_iter.current_buffer_.size() > 0)
|
||||||
|
break;
|
||||||
|
++new_iter.current_;
|
||||||
|
}
|
||||||
|
return new_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct an iterator representing the end of the buffers' data.
|
||||||
|
static buffers_iterator end(const BufferSequence& buffers)
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
||||||
|
__attribute__ ((__noinline__))
|
||||||
|
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
||||||
|
{
|
||||||
|
buffers_iterator new_iter;
|
||||||
|
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
|
||||||
|
new_iter.current_ = asio::buffer_sequence_begin(buffers);
|
||||||
|
new_iter.end_ = asio::buffer_sequence_end(buffers);
|
||||||
|
while (new_iter.current_ != new_iter.end_)
|
||||||
|
{
|
||||||
|
buffer_type buffer = *new_iter.current_;
|
||||||
|
new_iter.position_ += buffer.size();
|
||||||
|
++new_iter.current_;
|
||||||
|
}
|
||||||
|
return new_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereference an iterator.
|
||||||
|
reference operator*() const
|
||||||
|
{
|
||||||
|
return dereference();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereference an iterator.
|
||||||
|
pointer operator->() const
|
||||||
|
{
|
||||||
|
return &dereference();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access an individual element.
|
||||||
|
reference operator[](std::ptrdiff_t difference) const
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(*this);
|
||||||
|
tmp.advance(difference);
|
||||||
|
return *tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increment operator (prefix).
|
||||||
|
buffers_iterator& operator++()
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increment operator (postfix).
|
||||||
|
buffers_iterator operator++(int)
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(*this);
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrement operator (prefix).
|
||||||
|
buffers_iterator& operator--()
|
||||||
|
{
|
||||||
|
decrement();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrement operator (postfix).
|
||||||
|
buffers_iterator operator--(int)
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(*this);
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Addition operator.
|
||||||
|
buffers_iterator& operator+=(std::ptrdiff_t difference)
|
||||||
|
{
|
||||||
|
advance(difference);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subtraction operator.
|
||||||
|
buffers_iterator& operator-=(std::ptrdiff_t difference)
|
||||||
|
{
|
||||||
|
advance(-difference);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Addition operator.
|
||||||
|
friend buffers_iterator operator+(const buffers_iterator& iter,
|
||||||
|
std::ptrdiff_t difference)
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(iter);
|
||||||
|
tmp.advance(difference);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Addition operator.
|
||||||
|
friend buffers_iterator operator+(std::ptrdiff_t difference,
|
||||||
|
const buffers_iterator& iter)
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(iter);
|
||||||
|
tmp.advance(difference);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subtraction operator.
|
||||||
|
friend buffers_iterator operator-(const buffers_iterator& iter,
|
||||||
|
std::ptrdiff_t difference)
|
||||||
|
{
|
||||||
|
buffers_iterator tmp(iter);
|
||||||
|
tmp.advance(-difference);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subtraction operator.
|
||||||
|
friend std::ptrdiff_t operator-(const buffers_iterator& a,
|
||||||
|
const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return b.distance_to(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test two iterators for equality.
|
||||||
|
friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return a.equal(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test two iterators for inequality.
|
||||||
|
friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return !a.equal(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two iterators.
|
||||||
|
friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return a.distance_to(b) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two iterators.
|
||||||
|
friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return !(b < a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two iterators.
|
||||||
|
friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return b < a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two iterators.
|
||||||
|
friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
|
||||||
|
{
|
||||||
|
return !(a < b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Dereference the iterator.
|
||||||
|
reference dereference() const
|
||||||
|
{
|
||||||
|
return static_cast<pointer>(
|
||||||
|
current_buffer_.data())[current_buffer_position_];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare two iterators for equality.
|
||||||
|
bool equal(const buffers_iterator& other) const
|
||||||
|
{
|
||||||
|
return position_ == other.position_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the iterator.
|
||||||
|
void increment()
|
||||||
|
{
|
||||||
|
ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
||||||
|
++position_;
|
||||||
|
|
||||||
|
// Check if the increment can be satisfied by the current buffer.
|
||||||
|
++current_buffer_position_;
|
||||||
|
if (current_buffer_position_ != current_buffer_.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the next non-empty buffer.
|
||||||
|
++current_;
|
||||||
|
current_buffer_position_ = 0;
|
||||||
|
while (current_ != end_)
|
||||||
|
{
|
||||||
|
current_buffer_ = *current_;
|
||||||
|
if (current_buffer_.size() > 0)
|
||||||
|
return;
|
||||||
|
++current_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement the iterator.
|
||||||
|
void decrement()
|
||||||
|
{
|
||||||
|
ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
|
||||||
|
--position_;
|
||||||
|
|
||||||
|
// Check if the decrement can be satisfied by the current buffer.
|
||||||
|
if (current_buffer_position_ != 0)
|
||||||
|
{
|
||||||
|
--current_buffer_position_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the previous non-empty buffer.
|
||||||
|
buffer_sequence_iterator_type iter = current_;
|
||||||
|
while (iter != begin_)
|
||||||
|
{
|
||||||
|
--iter;
|
||||||
|
buffer_type buffer = *iter;
|
||||||
|
std::size_t buffer_size = buffer.size();
|
||||||
|
if (buffer_size > 0)
|
||||||
|
{
|
||||||
|
current_ = iter;
|
||||||
|
current_buffer_ = buffer;
|
||||||
|
current_buffer_position_ = buffer_size - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance the iterator by the specified distance.
|
||||||
|
void advance(std::ptrdiff_t n)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
std::ptrdiff_t current_buffer_balance
|
||||||
|
= current_buffer_.size() - current_buffer_position_;
|
||||||
|
|
||||||
|
// Check if the advance can be satisfied by the current buffer.
|
||||||
|
if (current_buffer_balance > n)
|
||||||
|
{
|
||||||
|
position_ += n;
|
||||||
|
current_buffer_position_ += n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position.
|
||||||
|
n -= current_buffer_balance;
|
||||||
|
position_ += current_buffer_balance;
|
||||||
|
|
||||||
|
// Move to next buffer. If it is empty then it will be skipped on the
|
||||||
|
// next iteration of this loop.
|
||||||
|
if (++current_ == end_)
|
||||||
|
{
|
||||||
|
ASIO_ASSERT(n == 0 && "iterator out of bounds");
|
||||||
|
current_buffer_ = buffer_type();
|
||||||
|
current_buffer_position_ = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_buffer_ = *current_;
|
||||||
|
current_buffer_position_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n < 0)
|
||||||
|
{
|
||||||
|
std::size_t abs_n = -n;
|
||||||
|
ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Check if the advance can be satisfied by the current buffer.
|
||||||
|
if (current_buffer_position_ >= abs_n)
|
||||||
|
{
|
||||||
|
position_ -= abs_n;
|
||||||
|
current_buffer_position_ -= abs_n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position.
|
||||||
|
abs_n -= current_buffer_position_;
|
||||||
|
position_ -= current_buffer_position_;
|
||||||
|
|
||||||
|
// Check if we've reached the beginning of the buffers.
|
||||||
|
if (current_ == begin_)
|
||||||
|
{
|
||||||
|
ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
|
||||||
|
current_buffer_position_ = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the previous non-empty buffer.
|
||||||
|
buffer_sequence_iterator_type iter = current_;
|
||||||
|
while (iter != begin_)
|
||||||
|
{
|
||||||
|
--iter;
|
||||||
|
buffer_type buffer = *iter;
|
||||||
|
std::size_t buffer_size = buffer.size();
|
||||||
|
if (buffer_size > 0)
|
||||||
|
{
|
||||||
|
current_ = iter;
|
||||||
|
current_buffer_ = buffer;
|
||||||
|
current_buffer_position_ = buffer_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the distance between two iterators.
|
||||||
|
std::ptrdiff_t distance_to(const buffers_iterator& other) const
|
||||||
|
{
|
||||||
|
return other.position_ - position_;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_type current_buffer_;
|
||||||
|
std::size_t current_buffer_position_;
|
||||||
|
buffer_sequence_iterator_type begin_;
|
||||||
|
buffer_sequence_iterator_type current_;
|
||||||
|
buffer_sequence_iterator_type end_;
|
||||||
|
std::size_t position_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Construct an iterator representing the beginning of the buffers' data.
|
||||||
|
template <typename BufferSequence>
|
||||||
|
inline buffers_iterator<BufferSequence> buffers_begin(
|
||||||
|
const BufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return buffers_iterator<BufferSequence>::begin(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct an iterator representing the end of the buffers' data.
|
||||||
|
template <typename BufferSequence>
|
||||||
|
inline buffers_iterator<BufferSequence> buffers_end(
|
||||||
|
const BufferSequence& buffers)
|
||||||
|
{
|
||||||
|
return buffers_iterator<BufferSequence>::end(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BUFFERS_ITERATOR_HPP
|
305
lib/asio/include/asio/cancellation_signal.hpp
Normal file
305
lib/asio/include/asio/cancellation_signal.hpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
//
|
||||||
|
// cancellation_signal.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_CANCELLATION_SIGNAL_HPP
|
||||||
|
#define ASIO_CANCELLATION_SIGNAL_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
#include "asio/cancellation_type.hpp"
|
||||||
|
#include "asio/detail/cstddef.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/detail/variadic_templates.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class cancellation_handler_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void call(cancellation_type_t) = 0;
|
||||||
|
virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~cancellation_handler_base() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
class cancellation_handler
|
||||||
|
: public cancellation_handler_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
template <typename... Args>
|
||||||
|
cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args)
|
||||||
|
: handler_(ASIO_MOVE_CAST(Args)(args)...),
|
||||||
|
size_(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
cancellation_handler(std::size_t size)
|
||||||
|
: handler_(),
|
||||||
|
size_(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \
|
||||||
|
template <ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
: handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \
|
||||||
|
size_(size) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF)
|
||||||
|
#undef ASIO_PRIVATE_HANDLER_CTOR_DEF
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
void call(cancellation_type_t type)
|
||||||
|
{
|
||||||
|
handler_(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
std::pair<void*, std::size_t> mem(this, size_);
|
||||||
|
this->cancellation_handler::~cancellation_handler();
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler& handler() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return handler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~cancellation_handler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler handler_;
|
||||||
|
std::size_t size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
class cancellation_slot;
|
||||||
|
|
||||||
|
/// A cancellation signal with a single slot.
|
||||||
|
class cancellation_signal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ASIO_CONSTEXPR cancellation_signal()
|
||||||
|
: handler_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ASIO_DECL ~cancellation_signal();
|
||||||
|
|
||||||
|
/// Emits the signal and causes invocation of the slot's handler, if any.
|
||||||
|
void emit(cancellation_type_t type)
|
||||||
|
{
|
||||||
|
if (handler_)
|
||||||
|
handler_->call(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the single slot associated with the signal.
|
||||||
|
/**
|
||||||
|
* The signal object must remain valid for as long the slot may be used.
|
||||||
|
* Destruction of the signal invalidates the slot.
|
||||||
|
*/
|
||||||
|
cancellation_slot slot() ASIO_NOEXCEPT;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cancellation_signal(const cancellation_signal&) ASIO_DELETED;
|
||||||
|
cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED;
|
||||||
|
|
||||||
|
detail::cancellation_handler_base* handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A slot associated with a cancellation signal.
|
||||||
|
class cancellation_slot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Creates a slot that is not connected to any cancellation signal.
|
||||||
|
ASIO_CONSTEXPR cancellation_slot()
|
||||||
|
: handler_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
/// Installs a handler into the slot, constructing the new object directly.
|
||||||
|
/**
|
||||||
|
* Destroys any existing handler in the slot, then installs the new handler,
|
||||||
|
* constructing it with the supplied @c args.
|
||||||
|
*
|
||||||
|
* The handler is a function object to be called when the signal is emitted.
|
||||||
|
* The signature of the handler must be
|
||||||
|
* @code void handler(asio::cancellation_type_t); @endcode
|
||||||
|
*
|
||||||
|
* @param args Arguments to be passed to the @c CancellationHandler object's
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* @returns A reference to the newly installed handler.
|
||||||
|
*
|
||||||
|
* @note Handlers installed into the slot via @c emplace are not required to
|
||||||
|
* be copy constructible or move constructible.
|
||||||
|
*/
|
||||||
|
template <typename CancellationHandler, typename... Args>
|
||||||
|
CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args)
|
||||||
|
{
|
||||||
|
typedef detail::cancellation_handler<CancellationHandler>
|
||||||
|
cancellation_handler_type;
|
||||||
|
auto_delete_helper del = { prepare_memory(
|
||||||
|
sizeof(cancellation_handler_type),
|
||||||
|
ASIO_ALIGNOF(CancellationHandler)) };
|
||||||
|
cancellation_handler_type* handler_obj =
|
||||||
|
new (del.mem.first) cancellation_handler_type(
|
||||||
|
del.mem.second, ASIO_MOVE_CAST(Args)(args)...);
|
||||||
|
del.mem.first = 0;
|
||||||
|
*handler_ = handler_obj;
|
||||||
|
return handler_obj->handler();
|
||||||
|
}
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename CancellationHandler>
|
||||||
|
CancellationHandler& emplace()
|
||||||
|
{
|
||||||
|
typedef detail::cancellation_handler<CancellationHandler>
|
||||||
|
cancellation_handler_type;
|
||||||
|
auto_delete_helper del = { prepare_memory(
|
||||||
|
sizeof(cancellation_handler_type),
|
||||||
|
ASIO_ALIGNOF(CancellationHandler)) };
|
||||||
|
cancellation_handler_type* handler_obj =
|
||||||
|
new (del.mem.first) cancellation_handler_type(del.mem.second);
|
||||||
|
del.mem.first = 0;
|
||||||
|
*handler_ = handler_obj;
|
||||||
|
return handler_obj->handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \
|
||||||
|
template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \
|
||||||
|
{ \
|
||||||
|
typedef detail::cancellation_handler<CancellationHandler> \
|
||||||
|
cancellation_handler_type; \
|
||||||
|
auto_delete_helper del = { prepare_memory( \
|
||||||
|
sizeof(cancellation_handler_type), \
|
||||||
|
ASIO_ALIGNOF(CancellationHandler)) }; \
|
||||||
|
cancellation_handler_type* handler_obj = \
|
||||||
|
new (del.mem.first) cancellation_handler_type( \
|
||||||
|
del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \
|
||||||
|
del.mem.first = 0; \
|
||||||
|
*handler_ = handler_obj; \
|
||||||
|
return handler_obj->handler(); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF)
|
||||||
|
#undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
/// Installs a handler into the slot.
|
||||||
|
/**
|
||||||
|
* Destroys any existing handler in the slot, then installs the new handler,
|
||||||
|
* constructing it as a decay-copy of the supplied handler.
|
||||||
|
*
|
||||||
|
* The handler is a function object to be called when the signal is emitted.
|
||||||
|
* The signature of the handler must be
|
||||||
|
* @code void handler(asio::cancellation_type_t); @endcode
|
||||||
|
*
|
||||||
|
* @param handler The handler to be installed.
|
||||||
|
*
|
||||||
|
* @returns A reference to the newly installed handler.
|
||||||
|
*/
|
||||||
|
template <typename CancellationHandler>
|
||||||
|
typename decay<CancellationHandler>::type& assign(
|
||||||
|
ASIO_MOVE_ARG(CancellationHandler) handler)
|
||||||
|
{
|
||||||
|
return this->emplace<typename decay<CancellationHandler>::type>(
|
||||||
|
ASIO_MOVE_CAST(CancellationHandler)(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the slot.
|
||||||
|
/**
|
||||||
|
* Destroys any existing handler in the slot.
|
||||||
|
*/
|
||||||
|
ASIO_DECL void clear();
|
||||||
|
|
||||||
|
/// Returns whether the slot is connected to a signal.
|
||||||
|
ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return handler_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the slot is connected and has an installed handler.
|
||||||
|
ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return handler_ != 0 && *handler_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two slots for equality.
|
||||||
|
friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs,
|
||||||
|
const cancellation_slot& rhs) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return lhs.handler_ == rhs.handler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two slots for inequality.
|
||||||
|
friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs,
|
||||||
|
const cancellation_slot& rhs) ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return lhs.handler_ != rhs.handler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class cancellation_signal;
|
||||||
|
|
||||||
|
ASIO_CONSTEXPR cancellation_slot(int,
|
||||||
|
detail::cancellation_handler_base** handler)
|
||||||
|
: handler_(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ASIO_DECL std::pair<void*, std::size_t> prepare_memory(
|
||||||
|
std::size_t size, std::size_t align);
|
||||||
|
|
||||||
|
struct auto_delete_helper
|
||||||
|
{
|
||||||
|
std::pair<void*, std::size_t> mem;
|
||||||
|
|
||||||
|
ASIO_DECL ~auto_delete_helper();
|
||||||
|
};
|
||||||
|
|
||||||
|
detail::cancellation_handler_base** handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return cancellation_slot(0, &handler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HEADER_ONLY)
|
||||||
|
# include "asio/impl/cancellation_signal.ipp"
|
||||||
|
#endif // defined(ASIO_HEADER_ONLY)
|
||||||
|
|
||||||
|
#endif // ASIO_CANCELLATION_SIGNAL_HPP
|
235
lib/asio/include/asio/cancellation_state.hpp
Normal file
235
lib/asio/include/asio/cancellation_state.hpp
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
//
|
||||||
|
// cancellation_state.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_CANCELLATION_STATE_HPP
|
||||||
|
#define ASIO_CANCELLATION_STATE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
#include "asio/cancellation_signal.hpp"
|
||||||
|
#include "asio/detail/cstddef.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// A simple cancellation signal propagation filter.
|
||||||
|
template <cancellation_type_t Mask>
|
||||||
|
struct cancellation_filter
|
||||||
|
{
|
||||||
|
/// Returns <tt>type & Mask</tt>.
|
||||||
|
cancellation_type_t operator()(
|
||||||
|
cancellation_type_t type) const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return type & Mask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A cancellation filter that disables cancellation.
|
||||||
|
typedef cancellation_filter<cancellation_type::none>
|
||||||
|
disable_cancellation;
|
||||||
|
|
||||||
|
/// A cancellation filter that enables terminal cancellation only.
|
||||||
|
typedef cancellation_filter<cancellation_type::terminal>
|
||||||
|
enable_terminal_cancellation;
|
||||||
|
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// A cancellation filter that enables terminal and partial cancellation.
|
||||||
|
typedef cancellation_filter<
|
||||||
|
cancellation_type::terminal | cancellation_type::partial>
|
||||||
|
enable_partial_cancellation;
|
||||||
|
|
||||||
|
/// A cancellation filter that enables terminal, partial and total cancellation.
|
||||||
|
typedef cancellation_filter<cancellation_type::terminal
|
||||||
|
| cancellation_type::partial | cancellation_type::total>
|
||||||
|
enable_total_cancellation;
|
||||||
|
|
||||||
|
#else // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
typedef cancellation_filter<
|
||||||
|
static_cast<cancellation_type_t>(
|
||||||
|
static_cast<unsigned int>(cancellation_type::terminal)
|
||||||
|
| static_cast<unsigned int>(cancellation_type::partial))>
|
||||||
|
enable_partial_cancellation;
|
||||||
|
|
||||||
|
typedef cancellation_filter<
|
||||||
|
static_cast<cancellation_type_t>(
|
||||||
|
static_cast<unsigned int>(cancellation_type::terminal)
|
||||||
|
| static_cast<unsigned int>(cancellation_type::partial)
|
||||||
|
| static_cast<unsigned int>(cancellation_type::total))>
|
||||||
|
enable_total_cancellation;
|
||||||
|
|
||||||
|
#endif // defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// A cancellation state is used for chaining signals and slots in compositions.
|
||||||
|
class cancellation_state
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Construct a disconnected cancellation state.
|
||||||
|
ASIO_CONSTEXPR cancellation_state() ASIO_NOEXCEPT
|
||||||
|
: impl_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and attach to a parent slot to create a new child slot.
|
||||||
|
/**
|
||||||
|
* Initialises the cancellation state so that it allows terminal cancellation
|
||||||
|
* only. Equivalent to <tt>cancellation_state(slot,
|
||||||
|
* enable_terminal_cancellation())</tt>.
|
||||||
|
*
|
||||||
|
* @param slot The parent cancellation slot to which the state will be
|
||||||
|
* attached.
|
||||||
|
*/
|
||||||
|
template <typename CancellationSlot>
|
||||||
|
ASIO_CONSTEXPR explicit cancellation_state(CancellationSlot slot)
|
||||||
|
: impl_(slot.is_connected() ? &slot.template emplace<impl<> >() : 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and attach to a parent slot to create a new child slot.
|
||||||
|
/**
|
||||||
|
* @param slot The parent cancellation slot to which the state will be
|
||||||
|
* attached.
|
||||||
|
*
|
||||||
|
* @param filter A function object that is used to transform incoming
|
||||||
|
* cancellation signals as they are received from the parent slot. This
|
||||||
|
* function object must have the signature:
|
||||||
|
* @code asio::cancellation_type_t filter(
|
||||||
|
* asio::cancellation_type_t); @endcode
|
||||||
|
*
|
||||||
|
* The library provides the following pre-defined cancellation filters:
|
||||||
|
*
|
||||||
|
* @li asio::disable_cancellation
|
||||||
|
* @li asio::enable_terminal_cancellation
|
||||||
|
* @li asio::enable_partial_cancellation
|
||||||
|
* @li asio::enable_total_cancellation
|
||||||
|
*/
|
||||||
|
template <typename CancellationSlot, typename Filter>
|
||||||
|
ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, Filter filter)
|
||||||
|
: impl_(slot.is_connected()
|
||||||
|
? &slot.template emplace<impl<Filter, Filter> >(filter, filter)
|
||||||
|
: 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct and attach to a parent slot to create a new child slot.
|
||||||
|
/**
|
||||||
|
* @param slot The parent cancellation slot to which the state will be
|
||||||
|
* attached.
|
||||||
|
*
|
||||||
|
* @param in_filter A function object that is used to transform incoming
|
||||||
|
* cancellation signals as they are received from the parent slot. This
|
||||||
|
* function object must have the signature:
|
||||||
|
* @code asio::cancellation_type_t in_filter(
|
||||||
|
* asio::cancellation_type_t); @endcode
|
||||||
|
*
|
||||||
|
* @param out_filter A function object that is used to transform outcoming
|
||||||
|
* cancellation signals as they are relayed to the child slot. This function
|
||||||
|
* object must have the signature:
|
||||||
|
* @code asio::cancellation_type_t out_filter(
|
||||||
|
* asio::cancellation_type_t); @endcode
|
||||||
|
*
|
||||||
|
* The library provides the following pre-defined cancellation filters:
|
||||||
|
*
|
||||||
|
* @li asio::disable_cancellation
|
||||||
|
* @li asio::enable_terminal_cancellation
|
||||||
|
* @li asio::enable_partial_cancellation
|
||||||
|
* @li asio::enable_total_cancellation
|
||||||
|
*/
|
||||||
|
template <typename CancellationSlot, typename InFilter, typename OutFilter>
|
||||||
|
ASIO_CONSTEXPR cancellation_state(CancellationSlot slot,
|
||||||
|
InFilter in_filter, OutFilter out_filter)
|
||||||
|
: impl_(slot.is_connected()
|
||||||
|
? &slot.template emplace<impl<InFilter, OutFilter> >(
|
||||||
|
ASIO_MOVE_CAST(InFilter)(in_filter),
|
||||||
|
ASIO_MOVE_CAST(OutFilter)(out_filter))
|
||||||
|
: 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the single child slot associated with the state.
|
||||||
|
/**
|
||||||
|
* This sub-slot is used with the operations that are being composed.
|
||||||
|
*/
|
||||||
|
ASIO_CONSTEXPR cancellation_slot slot() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_ ? impl_->signal_.slot() : cancellation_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the cancellation types that have been triggered.
|
||||||
|
cancellation_type_t cancelled() const ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
return impl_ ? impl_->cancelled_ : cancellation_type_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the specified cancellation types, if they have been triggered.
|
||||||
|
void clear(cancellation_type_t mask = cancellation_type::all)
|
||||||
|
ASIO_NOEXCEPT
|
||||||
|
{
|
||||||
|
if (impl_)
|
||||||
|
impl_->cancelled_ &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct impl_base
|
||||||
|
{
|
||||||
|
impl_base()
|
||||||
|
: cancelled_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cancellation_signal signal_;
|
||||||
|
cancellation_type_t cancelled_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename InFilter = enable_terminal_cancellation,
|
||||||
|
typename OutFilter = InFilter>
|
||||||
|
struct impl : impl_base
|
||||||
|
{
|
||||||
|
impl()
|
||||||
|
: in_filter_(),
|
||||||
|
out_filter_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl(InFilter in_filter, OutFilter out_filter)
|
||||||
|
: in_filter_(ASIO_MOVE_CAST(InFilter)(in_filter)),
|
||||||
|
out_filter_(ASIO_MOVE_CAST(OutFilter)(out_filter))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(cancellation_type_t in)
|
||||||
|
{
|
||||||
|
this->cancelled_ = in_filter_(in);
|
||||||
|
cancellation_type_t out = out_filter_(this->cancelled_);
|
||||||
|
if (out != cancellation_type::none)
|
||||||
|
this->signal_.emit(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
InFilter in_filter_;
|
||||||
|
OutFilter out_filter_;
|
||||||
|
};
|
||||||
|
|
||||||
|
impl_base* impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_CANCELLATION_STATE_HPP
|
174
lib/asio/include/asio/cancellation_type.hpp
Normal file
174
lib/asio/include/asio/cancellation_type.hpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// cancellation_type.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_CANCELLATION_TYPE_HPP
|
||||||
|
#define ASIO_CANCELLATION_TYPE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
# if defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Enumeration representing the different types of cancellation that may
|
||||||
|
/// be requested from or implemented by an asynchronous operation.
|
||||||
|
enum cancellation_type
|
||||||
|
{
|
||||||
|
/// Bitmask representing no types of cancellation.
|
||||||
|
none = 0,
|
||||||
|
|
||||||
|
/// Requests cancellation where, following a successful cancellation, the only
|
||||||
|
/// safe operations on the I/O object are closure or destruction.
|
||||||
|
terminal = 1,
|
||||||
|
|
||||||
|
/// Requests cancellation where a successful cancellation may result in
|
||||||
|
/// partial side effects or no side effects. Following cancellation, the I/O
|
||||||
|
/// object is in a well-known state, and may be used for further operations.
|
||||||
|
partial = 2,
|
||||||
|
|
||||||
|
/// Requests cancellation where a successful cancellation results in no
|
||||||
|
/// apparent side effects. Following cancellation, the I/O object is in the
|
||||||
|
/// same observable state as it was prior to the operation.
|
||||||
|
total = 4,
|
||||||
|
|
||||||
|
/// Bitmask representing all types of cancellation.
|
||||||
|
all = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Portability typedef.
|
||||||
|
typedef cancellation_type cancellation_type_t;
|
||||||
|
|
||||||
|
#elif defined(ASIO_HAS_ENUM_CLASS)
|
||||||
|
|
||||||
|
enum class cancellation_type : unsigned int
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
terminal = 1,
|
||||||
|
partial = 2,
|
||||||
|
total = 4,
|
||||||
|
all = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef cancellation_type cancellation_type_t;
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_ENUM_CLASS)
|
||||||
|
|
||||||
|
namespace cancellation_type {
|
||||||
|
|
||||||
|
enum cancellation_type_t
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
terminal = 1,
|
||||||
|
partial = 2,
|
||||||
|
total = 4,
|
||||||
|
all = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cancellation_type
|
||||||
|
|
||||||
|
typedef cancellation_type::cancellation_type_t cancellation_type_t;
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_ENUM_CLASS)
|
||||||
|
|
||||||
|
/// Negation operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline ASIO_CONSTEXPR bool operator!(cancellation_type_t x)
|
||||||
|
{
|
||||||
|
return static_cast<unsigned int>(x) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise and operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline ASIO_CONSTEXPR cancellation_type_t operator&(
|
||||||
|
cancellation_type_t x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
return static_cast<cancellation_type_t>(
|
||||||
|
static_cast<unsigned int>(x) & static_cast<unsigned int>(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise or operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline ASIO_CONSTEXPR cancellation_type_t operator|(
|
||||||
|
cancellation_type_t x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
return static_cast<cancellation_type_t>(
|
||||||
|
static_cast<unsigned int>(x) | static_cast<unsigned int>(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise xor operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline ASIO_CONSTEXPR cancellation_type_t operator^(
|
||||||
|
cancellation_type_t x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
return static_cast<cancellation_type_t>(
|
||||||
|
static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise negation operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline ASIO_CONSTEXPR cancellation_type_t operator~(cancellation_type_t x)
|
||||||
|
{
|
||||||
|
return static_cast<cancellation_type_t>(~static_cast<unsigned int>(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise and-assignment operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline cancellation_type_t& operator&=(
|
||||||
|
cancellation_type_t& x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
x = x & y;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise or-assignment operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline cancellation_type_t& operator|=(
|
||||||
|
cancellation_type_t& x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
x = x | y;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitwise xor-assignment operator.
|
||||||
|
/**
|
||||||
|
* @relates cancellation_type
|
||||||
|
*/
|
||||||
|
inline cancellation_type_t& operator^=(
|
||||||
|
cancellation_type_t& x, cancellation_type_t y)
|
||||||
|
{
|
||||||
|
x = x ^ y;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_CANCELLATION_TYPE_HPP
|
523
lib/asio/include/asio/co_spawn.hpp
Normal file
523
lib/asio/include/asio/co_spawn.hpp
Normal file
@ -0,0 +1,523 @@
|
|||||||
|
//
|
||||||
|
// co_spawn.hpp
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_CO_SPAWN_HPP
|
||||||
|
#define ASIO_CO_SPAWN_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include "asio/awaitable.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct awaitable_signature;
|
||||||
|
|
||||||
|
template <typename T, typename Executor>
|
||||||
|
struct awaitable_signature<awaitable<T, Executor>>
|
||||||
|
{
|
||||||
|
typedef void type(std::exception_ptr, T);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Executor>
|
||||||
|
struct awaitable_signature<awaitable<void, Executor>>
|
||||||
|
{
|
||||||
|
typedef void type(std::exception_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ex The executor that will be used to schedule the new thread of
|
||||||
|
* execution.
|
||||||
|
*
|
||||||
|
* @param a The asio::awaitable object that is the result of calling the
|
||||||
|
* coroutine's entry point function.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification that
|
||||||
|
* the thread of execution has completed. The function signature of the
|
||||||
|
* completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr, T); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr, T) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<std::size_t> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* std::size_t bytes_transferred = 0;
|
||||||
|
*
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* bytes_transferred += n;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception&)
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* co_return bytes_transferred;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_executor,
|
||||||
|
* echo(std::move(my_tcp_socket)),
|
||||||
|
* [](std::exception_ptr e, std::size_t n)
|
||||||
|
* {
|
||||||
|
* std::cout << "transferred " << n << "\n";
|
||||||
|
* });
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename Executor, typename T, typename AwaitableExecutor,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(
|
||||||
|
void(std::exception_ptr, T)) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||||
|
inline ASIO_INITFN_AUTO_RESULT_TYPE(
|
||||||
|
CompletionToken, void(std::exception_ptr, T))
|
||||||
|
co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
|
||||||
|
typename constraint<
|
||||||
|
(is_executor<Executor>::value || execution::is_executor<Executor>::value)
|
||||||
|
&& is_convertible<Executor, AwaitableExecutor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ex The executor that will be used to schedule the new thread of
|
||||||
|
* execution.
|
||||||
|
*
|
||||||
|
* @param a The asio::awaitable object that is the result of calling the
|
||||||
|
* coroutine's entry point function.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification that
|
||||||
|
* the thread of execution has completed. The function signature of the
|
||||||
|
* completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<void> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception& e)
|
||||||
|
* {
|
||||||
|
* std::cerr << "Exception: " << e.what() << "\n";
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_executor,
|
||||||
|
* echo(std::move(my_tcp_socket)),
|
||||||
|
* asio::detached);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename Executor, typename AwaitableExecutor,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(
|
||||||
|
void(std::exception_ptr)) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||||
|
inline ASIO_INITFN_AUTO_RESULT_TYPE(
|
||||||
|
CompletionToken, void(std::exception_ptr))
|
||||||
|
co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
|
||||||
|
typename constraint<
|
||||||
|
(is_executor<Executor>::value || execution::is_executor<Executor>::value)
|
||||||
|
&& is_convertible<Executor, AwaitableExecutor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ctx An execution context that will provide the executor to be used to
|
||||||
|
* schedule the new thread of execution.
|
||||||
|
*
|
||||||
|
* @param a The asio::awaitable object that is the result of calling the
|
||||||
|
* coroutine's entry point function.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification that
|
||||||
|
* the thread of execution has completed. The function signature of the
|
||||||
|
* completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr, T) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<std::size_t> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* std::size_t bytes_transferred = 0;
|
||||||
|
*
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* bytes_transferred += n;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception&)
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* co_return bytes_transferred;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_io_context,
|
||||||
|
* echo(std::move(my_tcp_socket)),
|
||||||
|
* [](std::exception_ptr e, std::size_t n)
|
||||||
|
* {
|
||||||
|
* std::cout << "transferred " << n << "\n";
|
||||||
|
* });
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext, typename T, typename AwaitableExecutor,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(
|
||||||
|
void(std::exception_ptr, T)) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(
|
||||||
|
typename ExecutionContext::executor_type)>
|
||||||
|
inline ASIO_INITFN_AUTO_RESULT_TYPE(
|
||||||
|
CompletionToken, void(std::exception_ptr, T))
|
||||||
|
co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(
|
||||||
|
typename ExecutionContext::executor_type),
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
&& is_convertible<typename ExecutionContext::executor_type,
|
||||||
|
AwaitableExecutor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ctx An execution context that will provide the executor to be used to
|
||||||
|
* schedule the new thread of execution.
|
||||||
|
*
|
||||||
|
* @param a The asio::awaitable object that is the result of calling the
|
||||||
|
* coroutine's entry point function.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification that
|
||||||
|
* the thread of execution has completed. The function signature of the
|
||||||
|
* completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr) @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<void> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception& e)
|
||||||
|
* {
|
||||||
|
* std::cerr << "Exception: " << e.what() << "\n";
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_io_context,
|
||||||
|
* echo(std::move(my_tcp_socket)),
|
||||||
|
* asio::detached);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext, typename AwaitableExecutor,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(
|
||||||
|
void(std::exception_ptr)) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(
|
||||||
|
typename ExecutionContext::executor_type)>
|
||||||
|
inline ASIO_INITFN_AUTO_RESULT_TYPE(
|
||||||
|
CompletionToken, void(std::exception_ptr))
|
||||||
|
co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(
|
||||||
|
typename ExecutionContext::executor_type),
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
&& is_convertible<typename ExecutionContext::executor_type,
|
||||||
|
AwaitableExecutor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ex The executor that will be used to schedule the new thread of
|
||||||
|
* execution.
|
||||||
|
*
|
||||||
|
* @param f A nullary function object with a return type of the form
|
||||||
|
* @c asio::awaitable<R,E> that will be used as the coroutine's entry
|
||||||
|
* point.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification
|
||||||
|
* that the thread of execution has completed. If @c R is @c void, the function
|
||||||
|
* signature of the completion handler must be:
|
||||||
|
*
|
||||||
|
* @code void handler(std::exception_ptr); @endcode
|
||||||
|
* Otherwise, the function signature of the completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr, R); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr, R) @endcode
|
||||||
|
* where @c R is the first template argument to the @c awaitable returned by the
|
||||||
|
* supplied function object @c F:
|
||||||
|
* @code asio::awaitable<R, AwaitableExecutor> F() @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<std::size_t> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* std::size_t bytes_transferred = 0;
|
||||||
|
*
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* bytes_transferred += n;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception&)
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* co_return bytes_transferred;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_executor,
|
||||||
|
* [socket = std::move(my_tcp_socket)]() mutable
|
||||||
|
* -> asio::awaitable<void>
|
||||||
|
* {
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception& e)
|
||||||
|
* {
|
||||||
|
* std::cerr << "Exception: " << e.what() << "\n";
|
||||||
|
* }
|
||||||
|
* }, asio::detached);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename Executor, typename F,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
|
||||||
|
typename result_of<F()>::type>::type) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
|
||||||
|
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
|
||||||
|
co_spawn(const Executor& ex, F&& f,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
|
||||||
|
typename constraint<
|
||||||
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Spawn a new coroutined-based thread of execution.
|
||||||
|
/**
|
||||||
|
* @param ctx An execution context that will provide the executor to be used to
|
||||||
|
* schedule the new thread of execution.
|
||||||
|
*
|
||||||
|
* @param f A nullary function object with a return type of the form
|
||||||
|
* @c asio::awaitable<R,E> that will be used as the coroutine's entry
|
||||||
|
* point.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will handle the notification
|
||||||
|
* that the thread of execution has completed. If @c R is @c void, the function
|
||||||
|
* signature of the completion handler must be:
|
||||||
|
*
|
||||||
|
* @code void handler(std::exception_ptr); @endcode
|
||||||
|
* Otherwise, the function signature of the completion handler must be:
|
||||||
|
* @code void handler(std::exception_ptr, R); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void(std::exception_ptr, R) @endcode
|
||||||
|
* where @c R is the first template argument to the @c awaitable returned by the
|
||||||
|
* supplied function object @c F:
|
||||||
|
* @code asio::awaitable<R, AwaitableExecutor> F() @endcode
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* @code
|
||||||
|
* asio::awaitable<std::size_t> echo(tcp::socket socket)
|
||||||
|
* {
|
||||||
|
* std::size_t bytes_transferred = 0;
|
||||||
|
*
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* bytes_transferred += n;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception&)
|
||||||
|
* {
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* co_return bytes_transferred;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
*
|
||||||
|
* asio::co_spawn(my_io_context,
|
||||||
|
* [socket = std::move(my_tcp_socket)]() mutable
|
||||||
|
* -> asio::awaitable<void>
|
||||||
|
* {
|
||||||
|
* try
|
||||||
|
* {
|
||||||
|
* char data[1024];
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* std::size_t n = co_await socket.async_read_some(
|
||||||
|
* asio::buffer(data), asio::use_awaitable);
|
||||||
|
*
|
||||||
|
* co_await asio::async_write(socket,
|
||||||
|
* asio::buffer(data, n), asio::use_awaitable);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* catch (const std::exception& e)
|
||||||
|
* {
|
||||||
|
* std::cerr << "Exception: " << e.what() << "\n";
|
||||||
|
* }
|
||||||
|
* }, asio::detached);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @par Per-Operation Cancellation
|
||||||
|
* The new thread of execution is created with a cancellation state that
|
||||||
|
* supports @c cancellation_type::terminal values only. To change the
|
||||||
|
* cancellation state, call asio::this_coro::reset_cancellation_state.
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext, typename F,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<
|
||||||
|
typename result_of<F()>::type>::type) CompletionToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(
|
||||||
|
typename ExecutionContext::executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
|
||||||
|
typename detail::awaitable_signature<typename result_of<F()>::type>::type)
|
||||||
|
co_spawn(ExecutionContext& ctx, F&& f,
|
||||||
|
CompletionToken&& token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(
|
||||||
|
typename ExecutionContext::executor_type),
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<ExecutionContext&, execution_context&>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/co_spawn.hpp"
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_CO_SPAWN_HPP
|
218
lib/asio/include/asio/completion_condition.hpp
Normal file
218
lib/asio/include/asio/completion_condition.hpp
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
//
|
||||||
|
// completion_condition.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_COMPLETION_CONDITION_HPP
|
||||||
|
#define ASIO_COMPLETION_CONDITION_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// The default maximum number of bytes to transfer in a single operation.
|
||||||
|
enum default_max_transfer_size_t { default_max_transfer_size = 65536 };
|
||||||
|
|
||||||
|
// Adapt result of old-style completion conditions (which had a bool result
|
||||||
|
// where true indicated that the operation was complete).
|
||||||
|
inline std::size_t adapt_completion_condition_result(bool result)
|
||||||
|
{
|
||||||
|
return result ? 0 : default_max_transfer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapt result of current completion conditions (which have a size_t result
|
||||||
|
// where 0 means the operation is complete, and otherwise the result is the
|
||||||
|
// maximum number of bytes to transfer on the next underlying operation).
|
||||||
|
inline std::size_t adapt_completion_condition_result(std::size_t result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
class transfer_all_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::size_t result_type;
|
||||||
|
|
||||||
|
template <typename Error>
|
||||||
|
std::size_t operator()(const Error& err, std::size_t)
|
||||||
|
{
|
||||||
|
return !!err ? 0 : default_max_transfer_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class transfer_at_least_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::size_t result_type;
|
||||||
|
|
||||||
|
explicit transfer_at_least_t(std::size_t minimum)
|
||||||
|
: minimum_(minimum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Error>
|
||||||
|
std::size_t operator()(const Error& err, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
return (!!err || bytes_transferred >= minimum_)
|
||||||
|
? 0 : default_max_transfer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t minimum_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class transfer_exactly_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::size_t result_type;
|
||||||
|
|
||||||
|
explicit transfer_exactly_t(std::size_t size)
|
||||||
|
: size_(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Error>
|
||||||
|
std::size_t operator()(const Error& err, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
return (!!err || bytes_transferred >= size_) ? 0 :
|
||||||
|
(size_ - bytes_transferred < default_max_transfer_size
|
||||||
|
? size_ - bytes_transferred : std::size_t(default_max_transfer_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup completion_condition Completion Condition Function Objects
|
||||||
|
*
|
||||||
|
* Function objects used for determining when a read or write operation should
|
||||||
|
* complete.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/// Return a completion condition function object that indicates that a read or
|
||||||
|
/// write operation should continue until all of the data has been transferred,
|
||||||
|
/// or until an error occurs.
|
||||||
|
/**
|
||||||
|
* This function is used to create an object, of unspecified type, that meets
|
||||||
|
* CompletionCondition requirements.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* Reading until a buffer is full:
|
||||||
|
* @code
|
||||||
|
* boost::array<char, 128> buf;
|
||||||
|
* asio::error_code ec;
|
||||||
|
* std::size_t n = asio::read(
|
||||||
|
* sock, asio::buffer(buf),
|
||||||
|
* asio::transfer_all(), ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // n == 128
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
unspecified transfer_all();
|
||||||
|
#else
|
||||||
|
inline detail::transfer_all_t transfer_all()
|
||||||
|
{
|
||||||
|
return detail::transfer_all_t();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Return a completion condition function object that indicates that a read or
|
||||||
|
/// write operation should continue until a minimum number of bytes has been
|
||||||
|
/// transferred, or until an error occurs.
|
||||||
|
/**
|
||||||
|
* This function is used to create an object, of unspecified type, that meets
|
||||||
|
* CompletionCondition requirements.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* Reading until a buffer is full or contains at least 64 bytes:
|
||||||
|
* @code
|
||||||
|
* boost::array<char, 128> buf;
|
||||||
|
* asio::error_code ec;
|
||||||
|
* std::size_t n = asio::read(
|
||||||
|
* sock, asio::buffer(buf),
|
||||||
|
* asio::transfer_at_least(64), ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // n >= 64 && n <= 128
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
unspecified transfer_at_least(std::size_t minimum);
|
||||||
|
#else
|
||||||
|
inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum)
|
||||||
|
{
|
||||||
|
return detail::transfer_at_least_t(minimum);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Return a completion condition function object that indicates that a read or
|
||||||
|
/// write operation should continue until an exact number of bytes has been
|
||||||
|
/// transferred, or until an error occurs.
|
||||||
|
/**
|
||||||
|
* This function is used to create an object, of unspecified type, that meets
|
||||||
|
* CompletionCondition requirements.
|
||||||
|
*
|
||||||
|
* @par Example
|
||||||
|
* Reading until a buffer is full or contains exactly 64 bytes:
|
||||||
|
* @code
|
||||||
|
* boost::array<char, 128> buf;
|
||||||
|
* asio::error_code ec;
|
||||||
|
* std::size_t n = asio::read(
|
||||||
|
* sock, asio::buffer(buf),
|
||||||
|
* asio::transfer_exactly(64), ec);
|
||||||
|
* if (ec)
|
||||||
|
* {
|
||||||
|
* // An error occurred.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // n == 64
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
unspecified transfer_exactly(std::size_t size);
|
||||||
|
#else
|
||||||
|
inline detail::transfer_exactly_t transfer_exactly(std::size_t size)
|
||||||
|
{
|
||||||
|
return detail::transfer_exactly_t(size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_COMPLETION_CONDITION_HPP
|
136
lib/asio/include/asio/compose.hpp
Normal file
136
lib/asio/include/asio/compose.hpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// compose.hpp
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_COMPOSE_HPP
|
||||||
|
#define ASIO_COMPOSE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Launch an asynchronous operation with a stateful implementation.
|
||||||
|
/**
|
||||||
|
* The async_compose function simplifies the implementation of composed
|
||||||
|
* asynchronous operations automatically wrapping a stateful function object
|
||||||
|
* with a conforming intermediate completion handler.
|
||||||
|
*
|
||||||
|
* @param implementation A function object that contains the implementation of
|
||||||
|
* the composed asynchronous operation. The first argument to the function
|
||||||
|
* object is a non-const reference to the enclosing intermediate completion
|
||||||
|
* handler. The remaining arguments are any arguments that originate from the
|
||||||
|
* completion handlers of any asynchronous operations performed by the
|
||||||
|
* implementation.
|
||||||
|
|
||||||
|
* @param token The completion token.
|
||||||
|
*
|
||||||
|
* @param io_objects_or_executors Zero or more I/O objects or I/O executors for
|
||||||
|
* which outstanding work must be maintained.
|
||||||
|
*
|
||||||
|
* @par Example:
|
||||||
|
*
|
||||||
|
* @code struct async_echo_implementation
|
||||||
|
* {
|
||||||
|
* tcp::socket& socket_;
|
||||||
|
* asio::mutable_buffer buffer_;
|
||||||
|
* enum { starting, reading, writing } state_;
|
||||||
|
*
|
||||||
|
* template <typename Self>
|
||||||
|
* void operator()(Self& self,
|
||||||
|
* asio::error_code error = {},
|
||||||
|
* std::size_t n = 0)
|
||||||
|
* {
|
||||||
|
* switch (state_)
|
||||||
|
* {
|
||||||
|
* case starting:
|
||||||
|
* state_ = reading;
|
||||||
|
* socket_.async_read_some(
|
||||||
|
* buffer_, std::move(self));
|
||||||
|
* break;
|
||||||
|
* case reading:
|
||||||
|
* if (error)
|
||||||
|
* {
|
||||||
|
* self.complete(error, 0);
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* state_ = writing;
|
||||||
|
* asio::async_write(socket_, buffer_,
|
||||||
|
* asio::transfer_exactly(n),
|
||||||
|
* std::move(self));
|
||||||
|
* }
|
||||||
|
* break;
|
||||||
|
* case writing:
|
||||||
|
* self.complete(error, n);
|
||||||
|
* break;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* template <typename CompletionToken>
|
||||||
|
* auto async_echo(tcp::socket& socket,
|
||||||
|
* asio::mutable_buffer buffer,
|
||||||
|
* CompletionToken&& token) ->
|
||||||
|
* typename asio::async_result<
|
||||||
|
* typename std::decay<CompletionToken>::type,
|
||||||
|
* void(asio::error_code, std::size_t)>::return_type
|
||||||
|
* {
|
||||||
|
* return asio::async_compose<CompletionToken,
|
||||||
|
* void(asio::error_code, std::size_t)>(
|
||||||
|
* async_echo_implementation{socket, buffer,
|
||||||
|
* async_echo_implementation::starting},
|
||||||
|
* token, socket);
|
||||||
|
* } @endcode
|
||||||
|
*/
|
||||||
|
template <typename CompletionToken, typename Signature,
|
||||||
|
typename Implementation, typename... IoObjectsOrExecutors>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
|
||||||
|
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
|
||||||
|
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
|
||||||
|
ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors);
|
||||||
|
|
||||||
|
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
template <typename CompletionToken, typename Signature, typename Implementation>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
|
||||||
|
async_compose(ASIO_MOVE_ARG(Implementation) implementation,
|
||||||
|
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token);
|
||||||
|
|
||||||
|
#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
|
||||||
|
template <typename CompletionToken, typename Signature, \
|
||||||
|
typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \
|
||||||
|
async_compose(ASIO_MOVE_ARG(Implementation) implementation, \
|
||||||
|
ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
|
||||||
|
ASIO_VARIADIC_MOVE_PARAMS(n));
|
||||||
|
/**/
|
||||||
|
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
|
||||||
|
#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/compose.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_COMPOSE_HPP
|
1172
lib/asio/include/asio/connect.hpp
Normal file
1172
lib/asio/include/asio/connect.hpp
Normal file
File diff suppressed because it is too large
Load Diff
83
lib/asio/include/asio/connect_pipe.hpp
Normal file
83
lib/asio/include/asio/connect_pipe.hpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// connect_pipe.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_CONNECT_PIPE_HPP
|
||||||
|
#define ASIO_CONNECT_PIPE_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_PIPE) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include "asio/basic_readable_pipe.hpp"
|
||||||
|
#include "asio/basic_writable_pipe.hpp"
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
typedef HANDLE native_pipe_handle;
|
||||||
|
#else // defined(ASIO_HAS_IOCP)
|
||||||
|
typedef int native_pipe_handle;
|
||||||
|
#endif // defined(ASIO_HAS_IOCP)
|
||||||
|
|
||||||
|
ASIO_DECL void create_pipe(native_pipe_handle p[2],
|
||||||
|
asio::error_code& ec);
|
||||||
|
|
||||||
|
ASIO_DECL void close_pipe(native_pipe_handle p);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Connect two pipe ends using an anonymous pipe.
|
||||||
|
/**
|
||||||
|
* @param read_end The read end of the pipe.
|
||||||
|
*
|
||||||
|
* @param write_end The write end of the pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*/
|
||||||
|
template <typename Executor1, typename Executor2>
|
||||||
|
void connect_pipe(basic_readable_pipe<Executor1>& read_end,
|
||||||
|
basic_writable_pipe<Executor2>& write_end);
|
||||||
|
|
||||||
|
/// Connect two pipe ends using an anonymous pipe.
|
||||||
|
/**
|
||||||
|
* @param read_end The read end of the pipe.
|
||||||
|
*
|
||||||
|
* @param write_end The write end of the pipe.
|
||||||
|
*
|
||||||
|
* @throws asio::system_error Thrown on failure.
|
||||||
|
*
|
||||||
|
* @param ec Set to indicate what error occurred, if any.
|
||||||
|
*/
|
||||||
|
template <typename Executor1, typename Executor2>
|
||||||
|
ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,
|
||||||
|
basic_writable_pipe<Executor2>& write_end, asio::error_code& ec);
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/connect_pipe.hpp"
|
||||||
|
#if defined(ASIO_HEADER_ONLY)
|
||||||
|
# include "asio/impl/connect_pipe.ipp"
|
||||||
|
#endif // defined(ASIO_HEADER_ONLY)
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_PIPE)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_CONNECT_PIPE_HPP
|
328
lib/asio/include/asio/coroutine.hpp
Normal file
328
lib/asio/include/asio/coroutine.hpp
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
//
|
||||||
|
// coroutine.hpp
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_COROUTINE_HPP
|
||||||
|
#define ASIO_COROUTINE_HPP
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class coroutine_ref;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Provides support for implementing stackless coroutines.
|
||||||
|
/**
|
||||||
|
* The @c coroutine class may be used to implement stackless coroutines. The
|
||||||
|
* class itself is used to store the current state of the coroutine.
|
||||||
|
*
|
||||||
|
* Coroutines are copy-constructible and assignable, and the space overhead is
|
||||||
|
* a single int. They can be used as a base class:
|
||||||
|
*
|
||||||
|
* @code class session : coroutine
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* }; @endcode
|
||||||
|
*
|
||||||
|
* or as a data member:
|
||||||
|
*
|
||||||
|
* @code class session
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* coroutine coro_;
|
||||||
|
* }; @endcode
|
||||||
|
*
|
||||||
|
* or even bound in as a function argument using lambdas or @c bind(). The
|
||||||
|
* important thing is that as the application maintains a copy of the object
|
||||||
|
* for as long as the coroutine must be kept alive.
|
||||||
|
*
|
||||||
|
* @par Pseudo-keywords
|
||||||
|
*
|
||||||
|
* A coroutine is used in conjunction with certain "pseudo-keywords", which
|
||||||
|
* are implemented as macros. These macros are defined by a header file:
|
||||||
|
*
|
||||||
|
* @code #include <asio/yield.hpp>@endcode
|
||||||
|
*
|
||||||
|
* and may conversely be undefined as follows:
|
||||||
|
*
|
||||||
|
* @code #include <asio/unyield.hpp>@endcode
|
||||||
|
*
|
||||||
|
* <b>reenter</b>
|
||||||
|
*
|
||||||
|
* The @c reenter macro is used to define the body of a coroutine. It takes a
|
||||||
|
* single argument: a pointer or reference to a coroutine object. For example,
|
||||||
|
* if the base class is a coroutine object you may write:
|
||||||
|
*
|
||||||
|
* @code reenter (this)
|
||||||
|
* {
|
||||||
|
* ... coroutine body ...
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* and if a data member or other variable you can write:
|
||||||
|
*
|
||||||
|
* @code reenter (coro_)
|
||||||
|
* {
|
||||||
|
* ... coroutine body ...
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* When @c reenter is executed at runtime, control jumps to the location of the
|
||||||
|
* last @c yield or @c fork.
|
||||||
|
*
|
||||||
|
* The coroutine body may also be a single statement, such as:
|
||||||
|
*
|
||||||
|
* @code reenter (this) for (;;)
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* @b Limitation: The @c reenter macro is implemented using a switch. This
|
||||||
|
* means that you must take care when using local variables within the
|
||||||
|
* coroutine body. The local variable is not allowed in a position where
|
||||||
|
* reentering the coroutine could bypass the variable definition.
|
||||||
|
*
|
||||||
|
* <b>yield <em>statement</em></b>
|
||||||
|
*
|
||||||
|
* This form of the @c yield keyword is often used with asynchronous operations:
|
||||||
|
*
|
||||||
|
* @code yield socket_->async_read_some(buffer(*buffer_), *this); @endcode
|
||||||
|
*
|
||||||
|
* This divides into four logical steps:
|
||||||
|
*
|
||||||
|
* @li @c yield saves the current state of the coroutine.
|
||||||
|
* @li The statement initiates the asynchronous operation.
|
||||||
|
* @li The resume point is defined immediately following the statement.
|
||||||
|
* @li Control is transferred to the end of the coroutine body.
|
||||||
|
*
|
||||||
|
* When the asynchronous operation completes, the function object is invoked
|
||||||
|
* and @c reenter causes control to transfer to the resume point. It is
|
||||||
|
* important to remember to carry the coroutine state forward with the
|
||||||
|
* asynchronous operation. In the above snippet, the current class is a
|
||||||
|
* function object object with a coroutine object as base class or data member.
|
||||||
|
*
|
||||||
|
* The statement may also be a compound statement, and this permits us to
|
||||||
|
* define local variables with limited scope:
|
||||||
|
*
|
||||||
|
* @code yield
|
||||||
|
* {
|
||||||
|
* mutable_buffers_1 b = buffer(*buffer_);
|
||||||
|
* socket_->async_read_some(b, *this);
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* <b>yield return <em>expression</em> ;</b>
|
||||||
|
*
|
||||||
|
* This form of @c yield is often used in generators or coroutine-based parsers.
|
||||||
|
* For example, the function object:
|
||||||
|
*
|
||||||
|
* @code struct interleave : coroutine
|
||||||
|
* {
|
||||||
|
* istream& is1;
|
||||||
|
* istream& is2;
|
||||||
|
* char operator()(char c)
|
||||||
|
* {
|
||||||
|
* reenter (this) for (;;)
|
||||||
|
* {
|
||||||
|
* yield return is1.get();
|
||||||
|
* yield return is2.get();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }; @endcode
|
||||||
|
*
|
||||||
|
* defines a trivial coroutine that interleaves the characters from two input
|
||||||
|
* streams.
|
||||||
|
*
|
||||||
|
* This type of @c yield divides into three logical steps:
|
||||||
|
*
|
||||||
|
* @li @c yield saves the current state of the coroutine.
|
||||||
|
* @li The resume point is defined immediately following the semicolon.
|
||||||
|
* @li The value of the expression is returned from the function.
|
||||||
|
*
|
||||||
|
* <b>yield ;</b>
|
||||||
|
*
|
||||||
|
* This form of @c yield is equivalent to the following steps:
|
||||||
|
*
|
||||||
|
* @li @c yield saves the current state of the coroutine.
|
||||||
|
* @li The resume point is defined immediately following the semicolon.
|
||||||
|
* @li Control is transferred to the end of the coroutine body.
|
||||||
|
*
|
||||||
|
* This form might be applied when coroutines are used for cooperative
|
||||||
|
* threading and scheduling is explicitly managed. For example:
|
||||||
|
*
|
||||||
|
* @code struct task : coroutine
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* void operator()()
|
||||||
|
* {
|
||||||
|
* reenter (this)
|
||||||
|
* {
|
||||||
|
* while (... not finished ...)
|
||||||
|
* {
|
||||||
|
* ... do something ...
|
||||||
|
* yield;
|
||||||
|
* ... do some more ...
|
||||||
|
* yield;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ...
|
||||||
|
* };
|
||||||
|
* ...
|
||||||
|
* task t1, t2;
|
||||||
|
* for (;;)
|
||||||
|
* {
|
||||||
|
* t1();
|
||||||
|
* t2();
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* <b>yield break ;</b>
|
||||||
|
*
|
||||||
|
* The final form of @c yield is used to explicitly terminate the coroutine.
|
||||||
|
* This form is comprised of two steps:
|
||||||
|
*
|
||||||
|
* @li @c yield sets the coroutine state to indicate termination.
|
||||||
|
* @li Control is transferred to the end of the coroutine body.
|
||||||
|
*
|
||||||
|
* Once terminated, calls to is_complete() return true and the coroutine cannot
|
||||||
|
* be reentered.
|
||||||
|
*
|
||||||
|
* Note that a coroutine may also be implicitly terminated if the coroutine
|
||||||
|
* body is exited without a yield, e.g. by return, throw or by running to the
|
||||||
|
* end of the body.
|
||||||
|
*
|
||||||
|
* <b>fork <em>statement</em></b>
|
||||||
|
*
|
||||||
|
* The @c fork pseudo-keyword is used when "forking" a coroutine, i.e. splitting
|
||||||
|
* it into two (or more) copies. One use of @c fork is in a server, where a new
|
||||||
|
* coroutine is created to handle each client connection:
|
||||||
|
*
|
||||||
|
* @code reenter (this)
|
||||||
|
* {
|
||||||
|
* do
|
||||||
|
* {
|
||||||
|
* socket_.reset(new tcp::socket(my_context_));
|
||||||
|
* yield acceptor->async_accept(*socket_, *this);
|
||||||
|
* fork server(*this)();
|
||||||
|
* } while (is_parent());
|
||||||
|
* ... client-specific handling follows ...
|
||||||
|
* } @endcode
|
||||||
|
*
|
||||||
|
* The logical steps involved in a @c fork are:
|
||||||
|
*
|
||||||
|
* @li @c fork saves the current state of the coroutine.
|
||||||
|
* @li The statement creates a copy of the coroutine and either executes it
|
||||||
|
* immediately or schedules it for later execution.
|
||||||
|
* @li The resume point is defined immediately following the semicolon.
|
||||||
|
* @li For the "parent", control immediately continues from the next line.
|
||||||
|
*
|
||||||
|
* The functions is_parent() and is_child() can be used to differentiate
|
||||||
|
* between parent and child. You would use these functions to alter subsequent
|
||||||
|
* control flow.
|
||||||
|
*
|
||||||
|
* Note that @c fork doesn't do the actual forking by itself. It is the
|
||||||
|
* application's responsibility to create a clone of the coroutine and call it.
|
||||||
|
* The clone can be called immediately, as above, or scheduled for delayed
|
||||||
|
* execution using something like asio::post().
|
||||||
|
*
|
||||||
|
* @par Alternate macro names
|
||||||
|
*
|
||||||
|
* If preferred, an application can use macro names that follow a more typical
|
||||||
|
* naming convention, rather than the pseudo-keywords. These are:
|
||||||
|
*
|
||||||
|
* @li @c ASIO_CORO_REENTER instead of @c reenter
|
||||||
|
* @li @c ASIO_CORO_YIELD instead of @c yield
|
||||||
|
* @li @c ASIO_CORO_FORK instead of @c fork
|
||||||
|
*/
|
||||||
|
class coroutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructs a coroutine in its initial state.
|
||||||
|
coroutine() : value_(0) {}
|
||||||
|
|
||||||
|
/// Returns true if the coroutine is the child of a fork.
|
||||||
|
bool is_child() const { return value_ < 0; }
|
||||||
|
|
||||||
|
/// Returns true if the coroutine is the parent of a fork.
|
||||||
|
bool is_parent() const { return !is_child(); }
|
||||||
|
|
||||||
|
/// Returns true if the coroutine has reached its terminal state.
|
||||||
|
bool is_complete() const { return value_ == -1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class detail::coroutine_ref;
|
||||||
|
int value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class coroutine_ref
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
coroutine_ref(coroutine& c) : value_(c.value_), modified_(false) {}
|
||||||
|
coroutine_ref(coroutine* c) : value_(c->value_), modified_(false) {}
|
||||||
|
~coroutine_ref() { if (!modified_) value_ = -1; }
|
||||||
|
operator int() const { return value_; }
|
||||||
|
int& operator=(int v) { modified_ = true; return value_ = v; }
|
||||||
|
private:
|
||||||
|
void operator=(const coroutine_ref&);
|
||||||
|
int& value_;
|
||||||
|
bool modified_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#define ASIO_CORO_REENTER(c) \
|
||||||
|
switch (::asio::detail::coroutine_ref _coro_value = c) \
|
||||||
|
case -1: if (_coro_value) \
|
||||||
|
{ \
|
||||||
|
goto terminate_coroutine; \
|
||||||
|
terminate_coroutine: \
|
||||||
|
_coro_value = -1; \
|
||||||
|
goto bail_out_of_coroutine; \
|
||||||
|
bail_out_of_coroutine: \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
else /* fall-through */ case 0:
|
||||||
|
|
||||||
|
#define ASIO_CORO_YIELD_IMPL(n) \
|
||||||
|
for (_coro_value = (n);;) \
|
||||||
|
if (_coro_value == 0) \
|
||||||
|
{ \
|
||||||
|
case (n): ; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
switch (_coro_value ? 0 : 1) \
|
||||||
|
for (;;) \
|
||||||
|
/* fall-through */ case -1: if (_coro_value) \
|
||||||
|
goto terminate_coroutine; \
|
||||||
|
else for (;;) \
|
||||||
|
/* fall-through */ case 1: if (_coro_value) \
|
||||||
|
goto bail_out_of_coroutine; \
|
||||||
|
else /* fall-through */ case 0:
|
||||||
|
|
||||||
|
#define ASIO_CORO_FORK_IMPL(n) \
|
||||||
|
for (_coro_value = -(n);; _coro_value = (n)) \
|
||||||
|
if (_coro_value == (n)) \
|
||||||
|
{ \
|
||||||
|
case -(n): ; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
else
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define ASIO_CORO_YIELD ASIO_CORO_YIELD_IMPL(__COUNTER__ + 1)
|
||||||
|
# define ASIO_CORO_FORK ASIO_CORO_FORK_IMPL(__COUNTER__ + 1)
|
||||||
|
#else // defined(_MSC_VER)
|
||||||
|
# define ASIO_CORO_YIELD ASIO_CORO_YIELD_IMPL(__LINE__)
|
||||||
|
# define ASIO_CORO_FORK ASIO_CORO_FORK_IMPL(__LINE__)
|
||||||
|
#endif // defined(_MSC_VER)
|
||||||
|
|
||||||
|
#endif // ASIO_COROUTINE_HPP
|
38
lib/asio/include/asio/deadline_timer.hpp
Normal file
38
lib/asio/include/asio/deadline_timer.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// deadline_timer.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DEADLINE_TIMER_HPP
|
||||||
|
#define ASIO_DEADLINE_TIMER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_BOOST_DATE_TIME) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
|
||||||
|
#include "asio/basic_deadline_timer.hpp"
|
||||||
|
|
||||||
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Typedef for the typical usage of timer. Uses a UTC clock.
|
||||||
|
typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#endif // ASIO_DEADLINE_TIMER_HPP
|
200
lib/asio/include/asio/defer.hpp
Normal file
200
lib/asio/include/asio/defer.hpp
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// defer.hpp
|
||||||
|
// ~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DEFER_HPP
|
||||||
|
#define ASIO_DEFER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include "asio/async_result.hpp"
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
#include "asio/execution_context.hpp"
|
||||||
|
#include "asio/execution/executor.hpp"
|
||||||
|
#include "asio/is_executor.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Submits a completion token or function object for execution.
|
||||||
|
/**
|
||||||
|
* This function submits an object for execution using the object's associated
|
||||||
|
* executor. The function object is queued for execution, and is never called
|
||||||
|
* from the current thread prior to returning from <tt>defer()</tt>.
|
||||||
|
*
|
||||||
|
* The use of @c defer(), rather than @ref post(), indicates the caller's
|
||||||
|
* preference that the executor defer the queueing of the function object. This
|
||||||
|
* may allow the executor to optimise queueing for cases when the function
|
||||||
|
* object represents a continuation of the current call context.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(); @endcode
|
||||||
|
*
|
||||||
|
* @returns This function returns <tt>async_initiate<NullaryToken,
|
||||||
|
* void()>(Init{}, token)</tt>, where @c Init is a function object type defined
|
||||||
|
* as:
|
||||||
|
*
|
||||||
|
* @code class Init
|
||||||
|
* {
|
||||||
|
* public:
|
||||||
|
* template <typename CompletionHandler>
|
||||||
|
* void operator()(CompletionHandler&& completion_handler) const;
|
||||||
|
* }; @endcode
|
||||||
|
*
|
||||||
|
* The function call operator of @c Init:
|
||||||
|
*
|
||||||
|
* @li Obtains the handler's associated executor object @c ex of type @c Ex by
|
||||||
|
* performing @code auto ex = get_associated_executor(handler); @endcode
|
||||||
|
*
|
||||||
|
* @li Obtains the handler's associated allocator object @c alloc by performing
|
||||||
|
* @code auto alloc = get_associated_allocator(handler); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
|
||||||
|
* @code execution::execute(
|
||||||
|
* prefer(
|
||||||
|
* require(ex, execution::blocking.never),
|
||||||
|
* execution::relationship.continuation,
|
||||||
|
* execution::allocator(alloc)),
|
||||||
|
* std::forward<CompletionHandler>(completion_handler)); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
|
||||||
|
* @code ex.defer(
|
||||||
|
* std::forward<CompletionHandler>(completion_handler),
|
||||||
|
* alloc); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void() @endcode
|
||||||
|
*/
|
||||||
|
template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer(
|
||||||
|
ASIO_MOVE_ARG(NullaryToken) token);
|
||||||
|
|
||||||
|
/// Submits a completion token or function object for execution.
|
||||||
|
/**
|
||||||
|
* This function submits an object for execution using the specified executor.
|
||||||
|
* The function object is queued for execution, and is never called from the
|
||||||
|
* current thread prior to returning from <tt>defer()</tt>.
|
||||||
|
*
|
||||||
|
* The use of @c defer(), rather than @ref post(), indicates the caller's
|
||||||
|
* preference that the executor defer the queueing of the function object. This
|
||||||
|
* may allow the executor to optimise queueing for cases when the function
|
||||||
|
* object represents a continuation of the current call context.
|
||||||
|
*
|
||||||
|
* @param ex The target executor.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(); @endcode
|
||||||
|
*
|
||||||
|
* @returns This function returns <tt>async_initiate<NullaryToken,
|
||||||
|
* void()>(Init{ex}, token)</tt>, where @c Init is a function object type
|
||||||
|
* defined as:
|
||||||
|
*
|
||||||
|
* @code class Init
|
||||||
|
* {
|
||||||
|
* public:
|
||||||
|
* using executor_type = Executor;
|
||||||
|
* explicit Init(const Executor& ex) : ex_(ex) {}
|
||||||
|
* executor_type get_executor() const noexcept { return ex_; }
|
||||||
|
* template <typename CompletionHandler>
|
||||||
|
* void operator()(CompletionHandler&& completion_handler) const;
|
||||||
|
* private:
|
||||||
|
* Executor ex_; // exposition only
|
||||||
|
* }; @endcode
|
||||||
|
*
|
||||||
|
* The function call operator of @c Init:
|
||||||
|
*
|
||||||
|
* @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by
|
||||||
|
* performing @code auto ex1 = get_associated_executor(handler, ex); @endcode
|
||||||
|
*
|
||||||
|
* @li Obtains the handler's associated allocator object @c alloc by performing
|
||||||
|
* @code auto alloc = get_associated_allocator(handler); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a
|
||||||
|
* function object @c f with a member @c executor_ that is initialised with
|
||||||
|
* <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c
|
||||||
|
* handler_ that is a decay-copy of @c completion_handler, and a function call
|
||||||
|
* operator that performs:
|
||||||
|
* @code auto a = get_associated_allocator(handler_);
|
||||||
|
* execution::execute(
|
||||||
|
* prefer(executor_,
|
||||||
|
* execution::blocking.possibly,
|
||||||
|
* execution::allocator(a)),
|
||||||
|
* std::move(handler_)); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a
|
||||||
|
* function object @c f with a member @c work_ that is initialised with
|
||||||
|
* <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of
|
||||||
|
* @c completion_handler, and a function call operator that performs:
|
||||||
|
* @code auto a = get_associated_allocator(handler_);
|
||||||
|
* work_.get_executor().dispatch(std::move(handler_), a);
|
||||||
|
* work_.reset(); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
|
||||||
|
* @code execution::execute(
|
||||||
|
* prefer(
|
||||||
|
* require(ex, execution::blocking.never),
|
||||||
|
* execution::relationship.continuation,
|
||||||
|
* execution::allocator(alloc)),
|
||||||
|
* std::move(f)); @endcode
|
||||||
|
*
|
||||||
|
* @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
|
||||||
|
* @code ex.defer(std::move(f), alloc); @endcode
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void() @endcode
|
||||||
|
*/
|
||||||
|
template <typename Executor,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer(
|
||||||
|
const Executor& ex,
|
||||||
|
ASIO_MOVE_ARG(NullaryToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
|
||||||
|
typename constraint<
|
||||||
|
execution::is_executor<Executor>::value || is_executor<Executor>::value
|
||||||
|
>::type = 0);
|
||||||
|
|
||||||
|
/// Submits a completion token or function object for execution.
|
||||||
|
/**
|
||||||
|
* @param ctx An execution context, from which the target executor is obtained.
|
||||||
|
*
|
||||||
|
* @param token The @ref completion_token that will be used to produce a
|
||||||
|
* completion handler. The function signature of the completion handler must be:
|
||||||
|
* @code void handler(); @endcode
|
||||||
|
*
|
||||||
|
* @returns <tt>defer(ctx.get_executor(), forward<NullaryToken>(token))</tt>.
|
||||||
|
*
|
||||||
|
* @par Completion Signature
|
||||||
|
* @code void() @endcode
|
||||||
|
*/
|
||||||
|
template <typename ExecutionContext,
|
||||||
|
ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(
|
||||||
|
typename ExecutionContext::executor_type)>
|
||||||
|
ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer(
|
||||||
|
ExecutionContext& ctx,
|
||||||
|
ASIO_MOVE_ARG(NullaryToken) token
|
||||||
|
ASIO_DEFAULT_COMPLETION_TOKEN(
|
||||||
|
typename ExecutionContext::executor_type),
|
||||||
|
typename constraint<is_convertible<
|
||||||
|
ExecutionContext&, execution_context&>::value>::type = 0);
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/defer.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_DEFER_HPP
|
112
lib/asio/include/asio/detached.hpp
Normal file
112
lib/asio/include/asio/detached.hpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
//
|
||||||
|
// detached.hpp
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DETACHED_HPP
|
||||||
|
#define ASIO_DETACHED_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include "asio/detail/type_traits.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Class used to specify that an asynchronous operation is detached.
|
||||||
|
/**
|
||||||
|
|
||||||
|
* The detached_t class is used to indicate that an asynchronous operation is
|
||||||
|
* detached. That is, there is no completion handler waiting for the
|
||||||
|
* operation's result. A detached_t object may be passed as a handler to an
|
||||||
|
* asynchronous operation, typically using the special value
|
||||||
|
* @c asio::detached. For example:
|
||||||
|
|
||||||
|
* @code my_socket.async_send(my_buffer, asio::detached);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
class detached_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
ASIO_CONSTEXPR detached_t()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adapts an executor to add the @c detached_t completion token as the
|
||||||
|
/// default.
|
||||||
|
template <typename InnerExecutor>
|
||||||
|
struct executor_with_default : InnerExecutor
|
||||||
|
{
|
||||||
|
/// Specify @c detached_t as the default completion token type.
|
||||||
|
typedef detached_t default_completion_token_type;
|
||||||
|
|
||||||
|
/// Construct the adapted executor from the inner executor type.
|
||||||
|
executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT
|
||||||
|
: InnerExecutor(ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert the specified executor to the inner executor type, then use
|
||||||
|
/// that to construct the adapted executor.
|
||||||
|
template <typename OtherExecutor>
|
||||||
|
executor_with_default(const OtherExecutor& ex,
|
||||||
|
typename constraint<
|
||||||
|
is_convertible<OtherExecutor, InnerExecutor>::value
|
||||||
|
>::type = 0) ASIO_NOEXCEPT
|
||||||
|
: InnerExecutor(ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Type alias to adapt an I/O object to use @c detached_t as its
|
||||||
|
/// default completion token type.
|
||||||
|
#if defined(ASIO_HAS_ALIAS_TEMPLATES) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
template <typename T>
|
||||||
|
using as_default_on_t = typename T::template rebind_executor<
|
||||||
|
executor_with_default<typename T::executor_type> >::other;
|
||||||
|
#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
/// Function helper to adapt an I/O object to use @c detached_t as its
|
||||||
|
/// default completion token type.
|
||||||
|
template <typename T>
|
||||||
|
static typename decay<T>::type::template rebind_executor<
|
||||||
|
executor_with_default<typename decay<T>::type::executor_type>
|
||||||
|
>::other
|
||||||
|
as_default_on(ASIO_MOVE_ARG(T) object)
|
||||||
|
{
|
||||||
|
return typename decay<T>::type::template rebind_executor<
|
||||||
|
executor_with_default<typename decay<T>::type::executor_type>
|
||||||
|
>::other(ASIO_MOVE_CAST(T)(object));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A special value, similar to std::nothrow.
|
||||||
|
/**
|
||||||
|
* See the documentation for asio::detached_t for a usage example.
|
||||||
|
*/
|
||||||
|
#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
|
||||||
|
constexpr detached_t detached;
|
||||||
|
#elif defined(ASIO_MSVC)
|
||||||
|
__declspec(selectany) detached_t detached;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/impl/detached.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_DETACHED_HPP
|
38
lib/asio/include/asio/detail/array.hpp
Normal file
38
lib/asio/include/asio/detail/array.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// detail/array.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DETAIL_ARRAY_HPP
|
||||||
|
#define ASIO_DETAIL_ARRAY_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/config.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
# include <array>
|
||||||
|
#else // defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
# include <boost/array.hpp>
|
||||||
|
#endif // defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
using std::array;
|
||||||
|
#else // defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
using boost::array;
|
||||||
|
#endif // defined(ASIO_HAS_STD_ARRAY)
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // ASIO_DETAIL_ARRAY_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user