Compare commits
3 Commits
main
...
enviroment
Author | SHA1 | Date | |
---|---|---|---|
db932b94a9 | |||
da6d57a280 | |||
c55650e12b |
8
.gitignore
vendored
8
.gitignore
vendored
@ -5,11 +5,3 @@ coverage
|
||||
doc/musique
|
||||
doc/build
|
||||
doc/source/api
|
||||
doc/*.html
|
||||
doc/*.pdf
|
||||
__pycache__
|
||||
drafts.cc
|
||||
.cache
|
||||
release_*
|
||||
*.zip
|
||||
*.html
|
||||
|
19
.gitlab-ci.yml
Normal file
19
.gitlab-ci.yml
Normal file
@ -0,0 +1,19 @@
|
||||
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
144
CHANGELOG.md
@ -1,144 +0,0 @@
|
||||
# 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
43
Dockerfile
@ -1,43 +0,0 @@
|
||||
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
|
||||
# left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = doc/build/
|
||||
OUTPUT_DIRECTORY = doc/build/doxygen/
|
||||
|
||||
# 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
|
||||
@ -485,13 +485,13 @@ NUM_PROC_THREADS = 1
|
||||
# normally produced when WARNINGS is set to YES.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_ALL = NO
|
||||
|
||||
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
||||
# be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
@ -864,7 +864,7 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = musique doc/index.md
|
||||
INPUT = src
|
||||
|
||||
# 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
|
||||
@ -952,7 +952,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = tests src/main.cc
|
||||
EXCLUDE = tests
|
||||
|
||||
# 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
|
||||
@ -1061,7 +1061,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (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.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = doc/index.md
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_HTML = YES
|
||||
GENERATE_HTML = NO
|
||||
|
||||
# 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
|
||||
@ -1582,7 +1582,7 @@ DISABLE_INDEX = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# 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.
|
||||
|
661
LICENSE
661
LICENSE
@ -1,661 +0,0 @@
|
||||
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/>.
|
96
Makefile
96
Makefile
@ -1,55 +1,71 @@
|
||||
include config.mk
|
||||
MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
|
||||
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
|
||||
|
||||
Sources := $(shell find musique/ -name '*.cc')
|
||||
Obj := $(subst musique/,,$(Sources:%.cc=%.o))
|
||||
Obj= \
|
||||
environment.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))
|
||||
Debug_Obj=$(addprefix bin/debug/,$(Obj))
|
||||
|
||||
ifeq ($(os),windows)
|
||||
all: bin/musique.exe
|
||||
debug: bin/windows/debug/musique.exe
|
||||
else
|
||||
all: bin/musique
|
||||
debug: bin/$(os)/debug/musique
|
||||
endif
|
||||
|
||||
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
|
||||
g++ $(CXXFLAGS) $(RELEASE_FLAGS) $(CPPFLAGS) -o $@ $< -c
|
||||
|
||||
doc: Doxyfile musique/*.cc musique/*.hh
|
||||
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
|
||||
cd doc; $(MAKE) html
|
||||
|
||||
.PHONY: doc-open
|
||||
doc-open: doc
|
||||
xdg-open ./doc/build/html/index.html
|
||||
|
||||
bin/unit-tests: src/tests/*.cc $(Debug_Obj)
|
||||
g++ $(CXXFLAGS) $(CPPFLAGS) $(DEBUG_FLAGS) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -rf bin coverage
|
||||
|
||||
release: bin/musique
|
||||
scripts/release
|
||||
.PHONY: clean
|
||||
|
||||
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)))
|
||||
$(shell mkdir -p bin/debug)
|
||||
|
53
README.md
53
README.md
@ -1,36 +1,37 @@
|
||||
# Musique interpreter
|
||||
|
||||
Reference implementation of Musique programming language.
|
||||
Interpreter języka Musique. Możliwy do wykorzystywania jako:
|
||||
|
||||
## Building
|
||||
- biblioteka interpretera języka dołączana do innego projektu (podobnie jak Lua);
|
||||
- REPL działający w systemie GNU/Linux + ALSA wykonujący język Musique.
|
||||
|
||||
Reference [`build_instructions.md`](./build_instructions.md).
|
||||
## Dostępne komendy
|
||||
|
||||
## Syntax highlighting
|
||||
- `make` - Buduje interpreter `bin/musique` (tryb release)
|
||||
- `make debug` - Buduje interpreter `bin/debug/musique` (tryb debug)
|
||||
- `make clean` - Usuwa reprodukowalne elementy projektu (automatycznie stworzone pliki binarne czy raporty)
|
||||
|
||||
### Vim / Neovim
|
||||
### Dokumentacja
|
||||
|
||||
Copy [editor/musique.vim](editor/musique.vim) to `syntax` directory inside your Vim (Neovim) configuration.
|
||||
- `make doc` - Tworzy `doc/build/html/` zawierający dokumentację projektu
|
||||
|
||||
### 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/
|
||||
```
|
||||
|
||||
Next, you can add bindings for filetype:
|
||||
|
||||
```vim
|
||||
au BufRead,BufNewFile *.mq set filetype=musique
|
||||
.
|
||||
├── bin Miejsce produkcji plików wykonywalnych
|
||||
├── coverage
|
||||
├── doc Dokumentacja języka, interpretera
|
||||
│ ├── build Miejsce produkcji dokumentacji
|
||||
│ └── 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.
|
||||
|
@ -1,27 +0,0 @@
|
||||
# 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
28
config.mk
@ -1,28 +0,0 @@
|
||||
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
Normal file
20
doc/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
55
doc/index.md
@ -1,55 +0,0 @@
|
||||
# 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.
|
@ -1,285 +0,0 @@
|
||||
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
180
doc/operators.md
@ -1,180 +0,0 @@
|
||||
# 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]
|
||||
```
|
5
doc/requirements.txt
Normal file
5
doc/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Sphinx==4.5.0
|
||||
breathe==4.33.1
|
||||
exhale==0.3.1
|
||||
recommonmark==0.7.1
|
||||
sphinx-rtd-theme==1.0.0
|
54
doc/składnia.txt
Normal file
54
doc/składnia.txt
Normal file
@ -0,0 +1,54 @@
|
||||
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 ? ;
|
55
doc/source/conf.py
Normal file
55
doc/source/conf.py
Normal file
@ -0,0 +1,55 @@
|
||||
# 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']
|
22
doc/source/index.rst
Normal file
22
doc/source/index.rst
Normal file
@ -0,0 +1,22 @@
|
||||
.. 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`
|
@ -1,298 +0,0 @@
|
||||
---
|
||||
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))
|
||||
```
|
@ -1,42 +0,0 @@
|
||||
" 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
17
editor/vscode-musique/.vscode/launch.json
vendored
@ -1,17 +0,0 @@
|
||||
// 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}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
.gitignore
|
||||
vsc-extension-quickstart.md
|
@ -1,9 +0,0 @@
|
||||
# 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
|
@ -1,65 +0,0 @@
|
||||
# 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!**
|
@ -1,26 +0,0 @@
|
||||
{
|
||||
"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": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}]
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
{
|
||||
"$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"
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
# 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.
|
3
examples/arithmetic.mq
Normal file
3
examples/arithmetic.mq
Normal file
@ -0,0 +1,3 @@
|
||||
say (1 + 3);
|
||||
say (3 * 10);
|
||||
say 42
|
@ -1,27 +0,0 @@
|
||||
----------------------------------
|
||||
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,
|
38
examples/church.mq
Normal file
38
examples/church.mq
Normal file
@ -0,0 +1,38 @@
|
||||
-- PAIR definition
|
||||
var pair = [x y | [z | z x y]];
|
||||
var car = [p | p [x y | x]];
|
||||
var cdr = [p | p [x y | y]];
|
||||
|
||||
var x = pair 100 200;
|
||||
say (car x);
|
||||
say (cdr x);
|
||||
|
||||
-- This two values should be builtin, but currently is not
|
||||
var true = (1 == 1);
|
||||
var false = (1 != 1);
|
||||
|
||||
-- LIST definition
|
||||
var null = pair true true;
|
||||
var is_empty = car;
|
||||
var head = [list | car (cdr list)];
|
||||
var tail = [list | cdr (cdr list)];
|
||||
var cons = [head tail | pair false (pair head tail)];
|
||||
|
||||
var for_each = [list iterator |
|
||||
if (is_empty list) [| nil ] [|
|
||||
iterator (head list);
|
||||
for_each (tail list) iterator ]];
|
||||
|
||||
var map = [list iterator |
|
||||
if (is_empty list) [| null ] [|
|
||||
cons (iterator (head list)) (map (tail list) iterator) ]];
|
||||
|
||||
var foldr = [list init folder |
|
||||
if (is_empty list)
|
||||
[| init ]
|
||||
[| foldr (tail list) (folder (head list) init) folder ]];
|
||||
|
||||
var range = [start stop | if (start >= stop) [|cons start null] [|cons start (range (start+1) stop)]];
|
||||
|
||||
var xs = range 1 5;
|
||||
say (foldr xs 1 [x y|x*y]);
|
@ -1,5 +0,0 @@
|
||||
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]),
|
||||
|
@ -1,13 +0,0 @@
|
||||
|
||||
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,30 +1,12 @@
|
||||
----------------------------------------------------------------------------
|
||||
This example shows how to implement factorial operation using different
|
||||
implementation techniques, showing how one can iterate and accumulate
|
||||
using Musique programming language
|
||||
----------------------------------------------------------------------------
|
||||
var for = [ start stop iteration |
|
||||
if (start > stop)
|
||||
[| nil ]
|
||||
[| iteration start; for (start + 1) stop iteration ]
|
||||
];
|
||||
|
||||
-- Calculate factorial using recursive approach
|
||||
factorial_recursive := (n |
|
||||
if (n <= 1)
|
||||
1
|
||||
(n * (factorial_recursive (n-1)))
|
||||
),
|
||||
var factorial = [n | if (n <= 1)
|
||||
[| 1]
|
||||
[| n * (factorial (n-1)) ]
|
||||
];
|
||||
|
||||
-- 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)),
|
||||
)
|
||||
),
|
||||
for 1 10 [i | say (factorial i)];
|
||||
|
@ -1,5 +0,0 @@
|
||||
fib := (n |
|
||||
if (n <= 1)
|
||||
n
|
||||
(fib (n-1) + fib (n-2))
|
||||
),
|
@ -1,65 +0,0 @@
|
||||
----------------------------------------------
|
||||
"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,
|
@ -1,21 +0,0 @@
|
||||
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,
|
||||
),
|
@ -1,13 +0,0 @@
|
||||
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),
|
@ -1,11 +0,0 @@
|
||||
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),
|
@ -1,6 +0,0 @@
|
||||
for (up 10) (n |
|
||||
snd := c + (pick (up 12)),
|
||||
o := if (n % 2 == 0) 3 4,
|
||||
say snd o,
|
||||
play (oct o, snd qn),
|
||||
),
|
@ -1,40 +0,0 @@
|
||||
--------------------------------------------------------------
|
||||
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]]),
|
||||
),
|
@ -1,13 +0,0 @@
|
||||
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
|
||||
),
|
||||
|
2
examples/variables.mq
Normal file
2
examples/variables.mq
Normal file
@ -0,0 +1,2 @@
|
||||
var x = 10;
|
||||
say (x + 1)
|
164
instruments.mq
164
instruments.mq
@ -1,164 +0,0 @@
|
||||
---------------------------------------------------------
|
||||
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,
|
@ -1,4 +0,0 @@
|
||||
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
2
lib/asio/include/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
@ -1,658 +0,0 @@
|
||||
# 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
|
@ -1,203 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,303 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,177 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,178 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,222 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,142 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,709 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,829 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,290 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,689 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,529 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,816 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,939 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,592 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,407 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,687 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,742 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,452 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,36 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,827 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,525 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,722 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,724 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,770 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,328 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,265 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,25 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,295 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,25 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,257 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,25 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,521 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,305 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,235 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,174 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,523 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,218 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,136 +0,0 @@
|
||||
//
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,328 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,200 +0,0 @@
|
||||
//
|
||||
// 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
|
@ -1,112 +0,0 @@
|
||||
//
|
||||
// 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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user